Support CDI devices in ctr --device flag

This change adds support for CDI devices to the ctr --device flag.
If a fully-qualified CDI device name is specified, this is injected
into the OCI specification before creating the container.

Note that the CDI specifications and the devices that they represent
are local and mirror the behaviour of linux devices in the ctr command.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
Evan Lezar
2023-05-17 16:15:46 +02:00
parent 80eb76332e
commit d3887b2e62
6 changed files with 94 additions and 30 deletions

View File

@@ -28,9 +28,11 @@ import (
"strconv"
"strings"
"github.com/container-orchestrated-devices/container-device-interface/pkg/cdi"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/platforms"
@@ -1622,3 +1624,32 @@ func WithWindowsNetworkNamespace(ns string) SpecOpts {
return nil
}
}
// WithCDIDevices injects the requested CDI devices into the OCI specification.
func WithCDIDevices(devices ...string) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if len(devices) == 0 {
return nil
}
registry := cdi.GetRegistry()
if err := registry.Refresh(); err != nil {
// We don't consider registry refresh failure a fatal error.
// For instance, a dynamically generated invalid CDI Spec file for
// any particular vendor shouldn't prevent injection of devices of
// different vendors. CDI itself knows better and it will fail the
// injection if necessary.
log.G(ctx).Warnf("CDI registry refresh failed: %v", err)
}
if _, err := registry.InjectDevices(s, devices...); err != nil {
return fmt.Errorf("CDI device injection failed: %w", err)
}
// One crucial thing to keep in mind is that CDI device injection
// might add OCI Spec environment variables, hooks, and mounts as
// well. Therefore it is important that none of the corresponding
// OCI Spec fields are reset up in the call stack once we return.
return nil
}
}