Merge pull request #50717 from elezar/match-on-device-driver-name

Match device driver on name and ignore capabilities
This commit is contained in:
Sebastiaan van Stijn
2025-08-14 20:20:19 +02:00
committed by GitHub
2 changed files with 34 additions and 15 deletions

View File

@@ -294,6 +294,11 @@ definitions:
description: "A request for devices to be sent to device drivers"
properties:
Driver:
description: |
The name of the device driver to use for this request.
Note that if this is specified the capabilities are ignored when
selecting a device driver.
type: "string"
example: "nvidia"
Count:
@@ -310,6 +315,12 @@ definitions:
Capabilities:
description: |
A list of capabilities; an OR list of AND lists of capabilities.
Note that if a driver is specified the capabilities have no effect on
selecting a driver as the driver name is used directly.
Note that if no driver is specified the capabilities are used to
select a driver with the required capabilities.
type: "array"
items:
type: "array"

View File

@@ -3,6 +3,7 @@ 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"
@@ -39,26 +40,33 @@ func registerDeviceDriver(name string, d *deviceDriver) {
func (daemon *Daemon) handleDevice(req container.DeviceRequest, spec *specs.Spec) error {
if req.Driver == "" {
for _, dd := range deviceDrivers {
// 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 {
// We add a special case for the CDI driver here as the cdi driver does
// not distinguish between capabilities.
// Furthermore, the "OR" and "AND" matching logic for the capability
// sets requires that a dummy capability be specified when constructing a
// DeviceRequest.
// This workaround can be removed once these device driver are
// refactored to be plugins, with each driver implementing its own
// matching logic, for example.
if req.Driver == "cdi" {
return dd.updateSpec(spec, &deviceInstance{req: req})
}
if selected := dd.capset.Match(req.Capabilities); selected != nil {
return dd.updateSpec(spec, &deviceInstance{req: req, selectedCaps: selected})
}
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}
}