| package daemon |
| |
| import ( |
| "errors" |
| "fmt" |
| "os/exec" |
| "strings" |
| |
| "github.com/moby/moby/v2/daemon/internal/capabilities" |
| "github.com/opencontainers/runtime-spec/specs-go" |
| "tags.cncf.io/container-device-interface/pkg/cdi" |
| ) |
| |
| const ( |
| amdContainerRuntimeExecutableName = "amd-container-runtime" |
| ) |
| |
| func setAMDGPUs(s *specs.Spec, dev *deviceInstance) error { |
| req := dev.req |
| if req.Count != 0 && len(req.DeviceIDs) > 0 { |
| return errConflictCountDeviceIDs |
| } |
| |
| switch { |
| case len(req.DeviceIDs) > 0: |
| s.Process.Env = append(s.Process.Env, "AMD_VISIBLE_DEVICES="+strings.Join(req.DeviceIDs, ",")) |
| case req.Count > 0: |
| s.Process.Env = append(s.Process.Env, "AMD_VISIBLE_DEVICES="+strings.Join(countToDevices(req.Count), ",")) |
| case req.Count < 0: |
| s.Process.Env = append(s.Process.Env, "AMD_VISIBLE_DEVICES=all") |
| case req.Count == 0: |
| s.Process.Env = append(s.Process.Env, "AMD_VISIBLE_DEVICES=void") |
| } |
| |
| return nil |
| } |
| |
| func createAMDCDIUpdater(cdiCache *cdi.Cache) func(*specs.Spec, *deviceInstance) error { |
| return func(s *specs.Spec, dev *deviceInstance) error { |
| vendor, err := getFirstAvailableVendor(cdiCache.ListVendors()) |
| if err != nil { |
| return fmt.Errorf("failed to discover GPU vendor from CDI: %w", err) |
| } |
| |
| if vendor != "amd.com" { |
| return errors.New("AMD CDI spec not found") |
| } |
| |
| injector := &cdiDeviceInjector{ |
| defaultCDIDeviceKind: "amd.com/gpu", |
| } |
| return injector.injectDevices(s, dev) |
| } |
| } |
| |
| func getAMDDeviceDrivers(cdiCache *cdi.Cache) *deviceDriver { |
| var composite firstSuccessfulUpdater |
| |
| if cdiCache != nil { |
| composite = append(composite, createAMDCDIUpdater(cdiCache)) |
| } |
| |
| if _, err := exec.LookPath(amdContainerRuntimeExecutableName); err == nil { |
| composite = append(composite, setAMDGPUs) |
| } |
| |
| if len(composite) == 0 { |
| return nil |
| } |
| |
| // We do not support specifying driver with device requests for AMD GPUs. |
| // Hence only use the composite updater and try cdi and runtime driver in sequence |
| // based on availability. |
| capset := capabilities.Set{"gpu": struct{}{}, "amd": struct{}{}} |
| return &deviceDriver{ |
| capset: capset, |
| updateSpec: composite.updateSpec, |
| } |
| } |