diff --git a/builder/builder-next/builder.go b/builder/builder-next/builder.go index 75b3c33b5f..04a55723c7 100644 --- a/builder/builder-next/builder.go +++ b/builder/builder-next/builder.go @@ -40,6 +40,7 @@ import ( "google.golang.org/grpc" grpcmetadata "google.golang.org/grpc/metadata" "google.golang.org/protobuf/proto" + "tags.cncf.io/container-device-interface/pkg/cdi" ) type errMultipleFilterValues struct{} @@ -97,7 +98,7 @@ type Opt struct { ContainerdAddress string ContainerdNamespace string Callbacks exporter.BuildkitCallbacks - CDISpecDirs []string + CDICache *cdi.Cache } // Builder can build using BuildKit backend diff --git a/builder/builder-next/controller.go b/builder/builder-next/controller.go index f2b4232503..3deb911baa 100644 --- a/builder/builder-next/controller.go +++ b/builder/builder-next/controller.go @@ -60,7 +60,6 @@ import ( "github.com/pkg/errors" bolt "go.etcd.io/bbolt" "go.opentelemetry.io/otel/sdk/trace" - "tags.cncf.io/container-device-interface/pkg/cdi" ) func newController(ctx context.Context, rt http.RoundTripper, opt Opt) (*control.Controller, error) { @@ -112,7 +111,7 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt dns := getDNSConfig(opt.DNSConfig) - cdiManager, err := getCDIManager(opt.CDISpecDirs) + cdiManager, err := getCDIManager(opt) if err != nil { return nil, err } @@ -341,7 +340,7 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt dns := getDNSConfig(opt.DNSConfig) - cdiManager, err := getCDIManager(opt.CDISpecDirs) + cdiManager, err := getCDIManager(opt) if err != nil { return nil, err } @@ -570,13 +569,10 @@ func getLabels(opt Opt, labels map[string]string) map[string]string { return labels } -func getCDIManager(specDirs []string) (*cdidevices.Manager, error) { - if len(specDirs) == 0 { +func getCDIManager(opt Opt) (*cdidevices.Manager, error) { + if opt.CDICache == nil { return nil, nil } - // Use the default CDI cache that was configured during daemon startup - cdiCache := cdi.GetDefaultCache() - // TODO: add support for auto-allowed devices from config - return cdidevices.NewManager(cdiCache, nil), nil + return cdidevices.NewManager(opt.CDICache, nil), nil } diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 0ac4036239..5148aec4b7 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -251,8 +251,9 @@ func (cli *daemonCLI) start(ctx context.Context) (err error) { // In order to lift this restriction the following would have to be addressed: // - Support needs to be added to the cdi package for injecting Windows devices: https://tags.cncf.io/container-device-interface/issues/28 // - The DeviceRequests API must be extended to non-linux platforms. + var cdiCache *cdi.Cache if cdiEnabled(cli.Config) { - daemon.RegisterCDIDriver(cli.Config.CDISpecDirs...) + cdiCache = daemon.RegisterCDIDriver(cli.Config.CDISpecDirs...) } var apiServer apiserver.Server @@ -289,7 +290,7 @@ func (cli *daemonCLI) start(ctx context.Context) (err error) { // initialized the cluster. d.RestartSwarmContainers() - b, shutdownBuildKit, err := initBuildkit(ctx, d) + b, shutdownBuildKit, err := initBuildkit(ctx, d, cdiCache) if err != nil { return fmt.Errorf("error initializing buildkit: %w", err) } @@ -390,7 +391,7 @@ func setOTLPProtoDefault() { } } -func initBuildkit(ctx context.Context, d *daemon.Daemon) (_ builderOptions, closeFn func(), _ error) { +func initBuildkit(ctx context.Context, d *daemon.Daemon, cdiCache *cdi.Cache) (_ builderOptions, closeFn func(), _ error) { log.G(ctx).Info("Initializing buildkit") closeFn = func() {} @@ -406,11 +407,6 @@ func initBuildkit(ctx context.Context, d *daemon.Daemon) (_ builderOptions, clos cfg := d.Config() - var cdiSpecDirs []string - if cdiEnabled(&cfg) { - cdiSpecDirs = cfg.CDISpecDirs - } - bk, err := buildkit.New(ctx, buildkit.Opt{ SessionManager: sm, Root: filepath.Join(cfg.Root, "buildkit"), @@ -432,7 +428,7 @@ func initBuildkit(ctx context.Context, d *daemon.Daemon) (_ builderOptions, clos Callbacks: exporter.BuildkitCallbacks{ Exported: d.ImageExportedByBuildkit, }, - CDISpecDirs: cdiSpecDirs, + CDICache: cdiCache, }) if err != nil { return builderOptions{}, closeFn, errors.Wrap(err, "error creating buildkit instance") diff --git a/daemon/cdi.go b/daemon/cdi.go index 5aed751e17..9e948a1723 100644 --- a/daemon/cdi.go +++ b/daemon/cdi.go @@ -22,14 +22,15 @@ type cdiHandler struct { // RegisterCDIDriver registers the CDI device driver. // The driver injects CDI devices into an incoming OCI spec and is called for DeviceRequests associated with CDI devices. // If the list of CDI spec directories is empty, the driver is not registered. -func RegisterCDIDriver(cdiSpecDirs ...string) { - driver := newCDIDeviceDriver(cdiSpecDirs...) +func RegisterCDIDriver(cdiSpecDirs ...string) *cdi.Cache { + driver, cache := newCDIDeviceDriver(cdiSpecDirs...) registerDeviceDriver("cdi", driver) + return cache } // newCDIDeviceDriver creates a new CDI device driver. // If the creation of the CDI cache fails, a driver is returned that will return an error on an injection request. -func newCDIDeviceDriver(cdiSpecDirs ...string) *deviceDriver { +func newCDIDeviceDriver(cdiSpecDirs ...string) (*deviceDriver, *cdi.Cache) { cache, err := createCDICache(cdiSpecDirs...) if err != nil { log.G(context.TODO()).WithError(err).Error("Failed to create CDI cache") @@ -47,7 +48,7 @@ func newCDIDeviceDriver(cdiSpecDirs ...string) *deviceDriver { Warnings: []string{fmt.Sprintf("CDI cache initialization failed: %v", err)}, }, nil }, - } + }, nil } // We construct a spec updates that injects CDI devices into the OCI spec using the initialized registry. @@ -58,7 +59,7 @@ func newCDIDeviceDriver(cdiSpecDirs ...string) *deviceDriver { return &deviceDriver{ updateSpec: c.injectCDIDevices, ListDevices: c.listDevices, - } + }, cache } // createCDICache creates a CDI cache for the specified CDI specification directories. @@ -68,13 +69,11 @@ func createCDICache(cdiSpecDirs ...string) (*cdi.Cache, error) { return nil, fmt.Errorf("no CDI specification directories specified") } - err := cdi.Configure(cdi.WithSpecDirs(cdiSpecDirs...)) + cache, err := cdi.NewCache(cdi.WithSpecDirs(cdiSpecDirs...)) if err != nil { return nil, fmt.Errorf("CDI registry initialization failure: %w", err) } - cache := cdi.GetDefaultCache() - for dir, errs := range cache.GetErrors() { for _, err := range errs { if errors.Is(err, os.ErrNotExist) { diff --git a/daemon/daemon.go b/daemon/daemon.go index a790a38598..8d40c768a9 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -86,6 +86,7 @@ import ( "google.golang.org/grpc/backoff" "google.golang.org/grpc/credentials/insecure" "resenje.org/singleflight" + "tags.cncf.io/container-device-interface/pkg/cdi" ) type configStore struct { @@ -149,6 +150,8 @@ type Daemon struct { mdDB *bolt.DB usesSnapshotter bool + + CDICache *cdi.Cache } // ID returns the daemon id