mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
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>
73 lines
2.3 KiB
Go
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}
|
|
}
|