Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions images/virtualization-dra/internal/plugin/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ func (d *Driver) UnprepareResourceClaims(ctx context.Context, claims []kubeletpl

func (d *Driver) unprepareResourceClaim(ctx context.Context, claim kubeletplugin.NamespacedObject) error {
if err := d.allocator.Unprepare(ctx, claim.UID); err != nil {
d.log.Error("error unpreparing devices for claim", slog.Any("error", err), slog.String("uid", string(claim.UID)))

return fmt.Errorf("error unpreparing devices for claim %v: %w", claim.UID, err)
}

Expand Down
18 changes: 15 additions & 3 deletions images/virtualization-dra/internal/usb-gateway/attach_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,29 @@ func (r *attachRecordManager) Refresh() error {
}

// keep only real entries
Comment thread
danilrwx marked this conversation as resolved.
var newEntries []AttachEntry
newEntries := make([]AttachEntry, 0, len(record.Entries))
for _, e := range record.Entries {
if _, ok := ports[e.Rhport]; ok {
newEntries = append(newEntries, e)
}
}

record.Entries = newEntries
newRecord := attachRecord{Entries: newEntries}
if slices.Equal(record.Entries, newRecord.Entries) {
r.record = newRecord
return nil
}

r.record = record
b, err = json.Marshal(newRecord)
if err != nil {
return err
}

if err = os.WriteFile(r.recordFile, b, 0o600); err != nil {
return err
}

r.record = newRecord
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ func (c *USBGatewayController) Detach(deviceName string) error {
}

entry := c.findEntry(deviceName)
if entry != nil {
if entry == nil {
log.Info("Device is already detached")
Comment thread
danilrwx marked this conversation as resolved.
} else {
log.Info("Detaching USB device")
err = c.usbIP.Detach(entry.Rhport)
if err != nil {
Expand All @@ -115,6 +117,10 @@ func (c *USBGatewayController) Detach(deviceName string) error {
return fmt.Errorf("failed to unexport device %s: %w", deviceName, err)
}

if err := c.attachRecordManager.Refresh(); err != nil {
return fmt.Errorf("failed to Refresh attach record after detach for device %s: %w", deviceName, err)
}

return nil
}

Expand Down
45 changes: 25 additions & 20 deletions images/virtualization-dra/internal/usb/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,29 +436,34 @@ func (s *AllocationStore) Unprepare(_ context.Context, claimUID types.UID) error
return fmt.Errorf("unprepare called before synchronize NRI Hook")
}

usbGatewayEnabled := featuregates.Default().USBGatewayEnabled()

allocatedDevices := s.resourceClaimAllocations[claimUID]
s.log.Info("Unpreparing devices", slog.Any("devices", allocatedDevices), slog.String("claimUID", string(claimUID)))

for _, device := range allocatedDevices {
if usbGatewayEnabled {
count := s.usbipAllocatedDevicesCount[device]
s.log.Info("Device attached by USBGateway", slog.String("device", device), slog.Int("count", count))
if count <= 1 {
s.log.Info("Detaching device because has only one consumer", slog.String("device", device))
if err := s.usbGateway.Detach(device); err != nil {
return fmt.Errorf("failed to detach device %s: %w", device, err)
allocatedDevices, exists := s.resourceClaimAllocations[claimUID]
if !exists || len(allocatedDevices) == 0 {
s.log.Info("Claim has no tracked allocations, skipping device cleanup", slog.String("claimUID", string(claimUID)))
} else {
usbGatewayEnabled := featuregates.Default().USBGatewayEnabled()

s.log.Info("Unpreparing devices", slog.Any("devices", allocatedDevices), slog.String("claimUID", string(claimUID)))

for _, device := range allocatedDevices {
if usbGatewayEnabled {
count, hasCount := s.usbipAllocatedDevicesCount[device]
s.log.Info("Device attached by USBGateway", slog.String("device", device), slog.Int("count", count))
switch {
case !hasCount || count <= 1:
s.log.Info("Device has no tracked consumers, attempting detach cleanup", slog.String("device", device), slog.Int("count", count))
if err := s.usbGateway.Detach(device); err != nil {
return fmt.Errorf("failed to detach device %s: %w", device, err)
}
delete(s.usbipAllocatedDevicesCount, device)
default:
s.log.Info("Decrementing device consumer count", slog.String("device", device), slog.Int("newCount", count-1))
s.usbipAllocatedDevicesCount[device]--
}
delete(s.usbipAllocatedDevicesCount, device)
} else {
s.log.Info("Decrementing device consumer count", slog.String("device", device), slog.Int("newCount", count-1))
s.usbipAllocatedDevicesCount[device]--
}
}

s.log.Info("Deleting device from allocated devices", slog.String("device", device))
s.allocatedDevices.Delete(device)
s.log.Info("Deleting device from allocated devices", slog.String("device", device))
s.allocatedDevices.Delete(device)
}
}

s.log.Info("Deleting CDI claim spec file", slog.String("claimUID", string(claimUID)))
Expand Down
7 changes: 4 additions & 3 deletions images/virtualization-dra/pkg/usbip/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,12 @@ func (e *usbExporter) Unexport(host, busID string, port int) error {
return fmt.Errorf("unsupported USBIP version: %d", unExportReply.Version)
}

if unExportReply.Status != protocol.OpStatusOk {
switch unExportReply.Status {
case protocol.OpStatusOk, protocol.OpStatusNoDev:
return nil
default:
return fmt.Errorf("reply failed: %s", unExportReply.Status.String())
}

return nil
}

func (e *usbExporter) usbipNetTCPConnect(host string, port int) (*net.TCPConn, error) {
Expand Down
Loading