Files
moby/daemon/devices.go
Evan Lezar 48038347d7 Match device driver on name and ignore capabilities
This change ignores requested capabilities when a driver is explicitly
requested. This simplifies the logic for selecting a driver and means
that users need not spefify redundant capabilities.

With the exception of the catch-all "gpu" capability the remaining
capabilities are only relevant for the "nvidia" driver.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-08-13 16:59:39 +02:00

73 lines
2.3 KiB
Go

package daemon
import (
"context"
"github.com/containerd/log"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/system"
"github.com/moby/moby/v2/daemon/config"
"github.com/moby/moby/v2/daemon/internal/capabilities"
"github.com/opencontainers/runtime-spec/specs-go"
)
var deviceDrivers = map[string]*deviceDriver{}
type deviceListing struct {
Devices []system.DeviceInfo
Warnings []string
}
type deviceDriver struct {
capset capabilities.Set
updateSpec func(*specs.Spec, *deviceInstance) error
// ListDevices returns a list of discoverable devices provided by this
// driver, any warnings encountered during the discovery, and an error if
// the overall listing operation failed.
// Can be nil if the driver does not provide a device listing.
ListDevices func(ctx context.Context, cfg *config.Config) (deviceListing, error)
}
type deviceInstance struct {
req container.DeviceRequest
selectedCaps []string
}
func registerDeviceDriver(name string, d *deviceDriver) {
deviceDrivers[name] = d
}
func (daemon *Daemon) handleDevice(req container.DeviceRequest, spec *specs.Spec) error {
if req.Driver == "" {
// If no driver is explicitly requested, we iterate over the registered
// drivers and attempt to match on capabilities.
for driver, dd := range deviceDrivers {
if selected := dd.capset.Match(req.Capabilities); selected != nil {
log.G(context.TODO()).WithFields(log.Fields{
"driver": driver,
"capabilities": map[string]any{
"requested": req.Capabilities,
"selected": selected,
},
}).Debugf("Selecting device driver by capabilities")
return dd.updateSpec(spec, &deviceInstance{req: req, selectedCaps: selected})
}
}
} else if dd := deviceDrivers[req.Driver]; dd != nil {
selected := dd.capset.Match(req.Capabilities)
// If a driver is explicitly requested and registered, then we use the
// specified driver, ignoring the capabilities.
log.G(context.TODO()).WithFields(log.Fields{
"driver": req.Driver,
"capabilities": map[string]any{
"requested": req.Capabilities,
"selected": selected,
},
}).Debugf("Selecting device driver by driver name; possibly ignoring capabilities")
return dd.updateSpec(spec, &deviceInstance{req: req, selectedCaps: selected})
}
return incompatibleDeviceRequest{req.Driver, req.Capabilities}
}