Skip to content

Commit 8c5a188

Browse files
committed
Fix remaining calculation
1 parent 3b86dfe commit 8c5a188

File tree

2 files changed

+41
-10
lines changed

2 files changed

+41
-10
lines changed

integration/vgpu_test.go

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,23 @@ func TestVGPU(t *testing.T) {
128128
require.Equal(t, images.StatusReady, img.Status, "Image should be ready")
129129
t.Log("Image ready")
130130

131-
// Step 3: Create instance with vGPU using QEMU hypervisor
131+
// Step 3: Check GPU resources BEFORE creating instance
132+
t.Log("Step 3: Recording GPU resources before instance creation...")
133+
profilesBefore, err := devices.ListGPUProfiles()
134+
require.NoError(t, err, "should list GPU profiles")
135+
var availableBefore int
136+
for _, p := range profilesBefore {
137+
if p.Name == profile {
138+
availableBefore = p.Available
139+
break
140+
}
141+
}
142+
require.Greater(t, availableBefore, 0, "profile should have availability before creation")
143+
t.Logf("Profile %q available instances before: %d", profile, availableBefore)
144+
145+
// Step 4: Create instance with vGPU using QEMU hypervisor
132146
// QEMU is required for vGPU/mdev passthrough with NVIDIA's vGPU manager
133-
t.Log("Step 3: Creating instance with vGPU profile:", profile)
147+
t.Log("Step 4: Creating instance with vGPU profile:", profile)
134148
inst, err := instanceManager.CreateInstance(ctx, instances.CreateInstanceRequest{
135149
Name: "vgpu-test",
136150
Image: imageName,
@@ -152,20 +166,37 @@ func TestVGPU(t *testing.T) {
152166
require.NotEmpty(t, inst.GPUMdevUUID, "Instance should have mdev UUID assigned")
153167
t.Logf("mdev UUID: %s", inst.GPUMdevUUID)
154168

155-
// Step 4: Verify mdev was created in sysfs
169+
// Step 5: Check GPU resources AFTER creating instance
170+
t.Run("ResourcesDecrementedAfterCreation", func(t *testing.T) {
171+
profilesAfter, err := devices.ListGPUProfiles()
172+
require.NoError(t, err, "should list GPU profiles after creation")
173+
174+
var availableAfter int
175+
for _, p := range profilesAfter {
176+
if p.Name == profile {
177+
availableAfter = p.Available
178+
break
179+
}
180+
}
181+
182+
t.Logf("Profile %q available instances after: %d (was %d)", profile, availableAfter, availableBefore)
183+
assert.Less(t, availableAfter, availableBefore, "available instances should decrease after creating VM")
184+
})
185+
186+
// Step 6: Verify mdev was created in sysfs
156187
t.Run("MdevCreated", func(t *testing.T) {
157188
mdevPath := "/sys/bus/mdev/devices/" + inst.GPUMdevUUID
158189
_, err := os.Stat(mdevPath)
159190
assert.NoError(t, err, "mdev device should exist at %s", mdevPath)
160191
t.Logf("mdev exists at: %s", mdevPath)
161192
})
162193

163-
// Step 5: Wait for guest agent to be ready
164-
t.Log("Step 5: Waiting for guest agent...")
194+
// Step 7: Wait for guest agent to be ready
195+
t.Log("Step 7: Waiting for guest agent...")
165196
err = waitForGuestAgent(ctx, instanceManager, inst.Id, 60*time.Second)
166197
require.NoError(t, err, "guest agent should be ready")
167198

168-
// Step 6: Verify GPU is visible inside VM via PCI
199+
// Step 8: Verify GPU is visible inside VM via PCI
169200
t.Run("GPUVisibleInVM", func(t *testing.T) {
170201
actualInst, err := instanceManager.GetInstance(ctx, inst.Id)
171202
require.NoError(t, err)
@@ -191,7 +222,7 @@ func TestVGPU(t *testing.T) {
191222
assert.Contains(t, output, "NVIDIA_FOUND", "NVIDIA GPU (vendor 0x10de) should be visible in guest")
192223
})
193224

194-
// Step 7: Check instance GPU info is correct
225+
// Step 9: Check instance GPU info is correct
195226
t.Run("InstanceGPUInfo", func(t *testing.T) {
196227
actualInst, err := instanceManager.GetInstance(ctx, inst.Id)
197228
require.NoError(t, err)

lib/devices/mdev.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ func countAvailableForSingleProfile(freeVFsByParent map[string][]VirtualFunction
237237
if len(parentVFs) == 0 {
238238
continue
239239
}
240-
// Sample just ONE VF per parent - all VFs on same parent have same profiles
240+
// Sample just ONE VF per parent - available_instances reflects GPU-wide capacity
241241
sampleVF := parentVFs[0]
242242
availPath := filepath.Join(mdevBusPath, sampleVF.PCIAddress, "mdev_supported_types", profileType, "available_instances")
243243
data, err := os.ReadFile(availPath)
@@ -248,8 +248,8 @@ func countAvailableForSingleProfile(freeVFsByParent map[string][]VirtualFunction
248248
if err != nil || instances < 1 {
249249
continue
250250
}
251-
// Profile is available - count all free VFs on this parent
252-
count += len(parentVFs)
251+
// available_instances reflects GPU-wide remaining capacity, not per-VF
252+
count += instances
253253
}
254254
return count
255255
}

0 commit comments

Comments
 (0)