mirror of
https://github.com/moby/moby.git
synced 2026-01-11 02:31:44 +00:00
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>
This commit is contained in:
@@ -293,6 +293,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:
|
||||
@@ -309,6 +314,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"
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user