Skip to content

Commit

Permalink
device-injector: add support for CDI injection.
Browse files Browse the repository at this point in the history
Add support for injecting annotated CDI devices using the
new native NRI CDI injection API.

Signed-off-by: Krisztian Litkey <[email protected]>
  • Loading branch information
klihub committed Jul 10, 2024
1 parent 16e1f9e commit 9aadde9
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 6 deletions.
31 changes: 29 additions & 2 deletions plugins/device-injector/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Device Injector Plugin

This sample plugin can inject devices and mounts into containers using
pod annotations.
This sample plugin can inject Linux device nodes, CDI devices, and mounts into
containers using pod annotations.

### Device Annotations

Expand All @@ -26,6 +26,33 @@ The annotation syntax for device injection is

`file_mode`, `uid` and `gid` can be omitted, the rest are mandatory.

### CDI Device Annotations

Devices are annotated using the `cdi-devices.nri.io` annotation key prefix.
The key `cdi-devices.nri.io/container.$CONTAINER_NAME` annotates CDI devices
to be injected into `$CONTAINER_NAME`. The keys `cdi-devices.nri.io` and
`cdi-devices.nri.io/pod` annotate CDI devices to be injected into all
containers of the pod.

The annotation value syntax is an array of CDI device names to inject. For
instance, the following annotation

```
metadata:
name: bash
annotations:
cdi-devices.nri.io/container.c0: |
- vendor0.com/device=null
cdi-devices.nri.io/container.c1: |
- vendor0.com/device=zero
cdi-devices.nri.io/container.mgmt: |
- vendor0.com/device=all
```

requests the injection of the vendor0.com/device=null, vendor0.com/device=zero,
and vendor0.com/device=all CDI devices, to the c0, c1, and mgmt containers of
the pod.

### Mount Annotations

Mounts are annotated in a similar manner to devices, but using the
Expand Down
66 changes: 62 additions & 4 deletions plugins/device-injector/device-injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const (
deviceKey = "devices.nri.io"
// Prefix of the key used for mount annotations.
mountKey = "mounts.nri.io"
// Prefix of the key used for CDI device annotations.
cdiDeviceKey = "cdi-devices.nri.io"
)

var (
Expand Down Expand Up @@ -69,10 +71,11 @@ type plugin struct {
// CreateContainer handles container creation requests.
func (p *plugin) CreateContainer(_ context.Context, pod *api.PodSandbox, container *api.Container) (*api.ContainerAdjustment, []*api.ContainerUpdate, error) {
var (
ctrName string
devices []device
mounts []mount
err error
ctrName string
devices []device
cdiDevices []string
mounts []mount
err error
)

ctrName = containerName(pod, container)
Expand Down Expand Up @@ -104,6 +107,31 @@ func (p *plugin) CreateContainer(_ context.Context, pod *api.PodSandbox, contain
}
}

// inject CDI devices to container
cdiDevices, err = parseCDIDevices(container.Name, pod.Annotations)
if err != nil {
return nil, nil, err
}

if len(cdiDevices) == 0 {
log.Infof("%s: no CDI devices annotated...", ctrName)
} else {
if verbose {
dump(ctrName, "annotated CDI devices", devices)
}

for _, name := range cdiDevices {
adjust.AddCDIDevice(
&api.CDIDevice{
Name: name,
},
)
if !verbose {
log.Infof("%s: injected CDI device %q...", ctrName, name)
}
}
}

// inject mounts to container
mounts, err = parseMounts(container.Name, pod.Annotations)
if err != nil {
Expand Down Expand Up @@ -162,6 +190,36 @@ func parseDevices(ctr string, annotations map[string]string) ([]device, error) {
return devices, nil
}

func parseCDIDevices(ctr string, annotations map[string]string) ([]string, error) {
var (
key string
annotation []byte
cdiDevices []string
)

// look up effective device annotation and unmarshal devices
for _, key = range []string{
cdiDeviceKey + "/container." + ctr,
cdiDeviceKey + "/pod",
cdiDeviceKey,
} {
if value, ok := annotations[key]; ok {
annotation = []byte(value)
break
}
}

if annotation == nil {
return nil, nil
}

if err := yaml.Unmarshal(annotation, &cdiDevices); err != nil {
return nil, fmt.Errorf("invalid CDI device annotation %q: %w", key, err)
}

return cdiDevices, nil
}

func parseMounts(ctr string, annotations map[string]string) ([]mount, error) {
var (
key string
Expand Down

0 comments on commit 9aadde9

Please sign in to comment.