|
| 1 | +// Package cdi has the primary purpose of providing an API for |
| 2 | +// interacting with CDI and consuming CDI devices. |
| 3 | +// |
| 4 | +// For more information about Container Device Interface, please refer to |
| 5 | +// https://github.com/container-orchestrated-devices/container-device-interface |
| 6 | +// |
| 7 | +// Container Device Interface |
| 8 | +// |
| 9 | +// Container Device Interface, or CDI for short, provides comprehensive |
| 10 | +// third party device support for container runtimes. CDI uses vendor |
| 11 | +// provided specification files, CDI Specs for short, to describe how a |
| 12 | +// container's runtime environment should be modified when one or more |
| 13 | +// of the vendor-specific devices is injected into the container. Beyond |
| 14 | +// describing the low level platform-specific details of how to gain |
| 15 | +// basic access to a device, CDI Specs allow more fine-grained device |
| 16 | +// initialization, and the automatic injection of any necessary vendor- |
| 17 | +// or device-specific software that might be required for a container |
| 18 | +// to use a device or take full advantage of it. |
| 19 | +// |
| 20 | +// In the CDI device model containers request access to a device using |
| 21 | +// fully qualified device names, qualified names for short, consisting of |
| 22 | +// a vendor identifier, a device class and a device name or identifier. |
| 23 | +// These pieces of information together uniquely identify a device among |
| 24 | +// all device vendors, classes and device instances. |
| 25 | +// |
| 26 | +// This package implements an API for easy consumption of CDI. The API |
| 27 | +// implements discovery, loading and caching of CDI Specs and injection |
| 28 | +// of CDI devices into containers. This is the most common functionality |
| 29 | +// the vast majority of CDI consumers need. The API should be usable both |
| 30 | +// by OCI runtime clients and runtime implementations. |
| 31 | +// |
| 32 | +// CDI Registry |
| 33 | +// |
| 34 | +// The primary interface to interact with CDI devices is the Registry. It |
| 35 | +// is essentially a cache of all Specs and devices discovered in standard |
| 36 | +// CDI directories on the host. The registry has two main functionality, |
| 37 | +// injecting devices into an OCI Spec and refreshing the cache of CDI |
| 38 | +// Specs and devices. |
| 39 | +// |
| 40 | +// Device Injection |
| 41 | +// |
| 42 | +// Using the Registry one can inject CDI devices into a container with code |
| 43 | +// similar to the following snippet: |
| 44 | +// |
| 45 | +// import ( |
| 46 | +// "fmt" |
| 47 | +// "strings" |
| 48 | +// |
| 49 | +// "github.com/pkg/errors" |
| 50 | +// log "github.com/sirupsen/logrus" |
| 51 | +// |
| 52 | +// "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" |
| 53 | +// oci "github.com/opencontainers/runtime-spec/specs-go" |
| 54 | +// ) |
| 55 | +// |
| 56 | +// func injectCDIDevices(spec *oci.Spec, devices []string) error { |
| 57 | +// log.Debug("pristine OCI Spec: %s", dumpSpec(spec)) |
| 58 | +// |
| 59 | +// unresolved, err := cdi.GetRegistry().InjectDevices(spec, devices) |
| 60 | +// if err != nil { |
| 61 | +// return errors.Wrap(err, "CDI device injection failed") |
| 62 | +// } |
| 63 | +// |
| 64 | +// log.Debug("CDI-updated OCI Spec: %s", dumpSpec(spec)) |
| 65 | +// return nil |
| 66 | +// } |
| 67 | +// |
| 68 | +// Cache Refresh |
| 69 | +// |
| 70 | +// In a runtime implementation one typically wants to make sure the |
| 71 | +// CDI Spec cache is up to date before performing device injection. |
| 72 | +// A code snippet similar to the following accmplishes that: |
| 73 | +// |
| 74 | +// import ( |
| 75 | +// "fmt" |
| 76 | +// "strings" |
| 77 | +// |
| 78 | +// "github.com/pkg/errors" |
| 79 | +// log "github.com/sirupsen/logrus" |
| 80 | +// |
| 81 | +// "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" |
| 82 | +// oci "github.com/opencontainers/runtime-spec/specs-go" |
| 83 | +// ) |
| 84 | +// |
| 85 | +// func injectCDIDevices(spec *oci.Spec, devices []string) error { |
| 86 | +// registry := cdi.GetRegistry() |
| 87 | +// |
| 88 | +// if err := registry.Refresh(); err != nil { |
| 89 | +// // Note: |
| 90 | +// // It is up to the implementation to decide whether |
| 91 | +// // to abort injection on errors. A failed Refresh() |
| 92 | +// // does not necessarily render the registry unusable. |
| 93 | +// // For instance, a parse error in a Spec file for |
| 94 | +// // vendor A does not have any effect on devices of |
| 95 | +// // vendor B... |
| 96 | +// log.Warnf("pre-injection Refresh() failed: %v", err) |
| 97 | +// } |
| 98 | +// |
| 99 | +// log.Debug("pristine OCI Spec: %s", dumpSpec(spec)) |
| 100 | +// |
| 101 | +// unresolved, err := registry.InjectDevices(spec, devices) |
| 102 | +// if err != nil { |
| 103 | +// return errors.Wrap(err, "CDI device injection failed") |
| 104 | +// } |
| 105 | +// |
| 106 | +// log.Debug("CDI-updated OCI Spec: %s", dumpSpec(spec)) |
| 107 | +// return nil |
| 108 | +// } |
| 109 | +// |
| 110 | +// Generated Spec Files, Multiple Directories, Device Precedence |
| 111 | +// |
| 112 | +// There are systems where the set of available or usable CDI devices |
| 113 | +// changes dynamically and this needs to be reflected in the CDI Specs. |
| 114 | +// This is done by dynamically regenerating CDI Spec files which are |
| 115 | +// affected by these changes. |
| 116 | +// |
| 117 | +// CDI can collect Spec files from multiple directories. Spec files are |
| 118 | +// automatically assigned priorities according to which directory they |
| 119 | +// were loaded from. The later a directory occurs in the list of CDI |
| 120 | +// directories to scan, the higher priority Spec files loaded from that |
| 121 | +// directory are assigned to. When two or more Spec files define the |
| 122 | +// same device, conflict is resolved by chosing the definition from the |
| 123 | +// Spec file with the highest priority. |
| 124 | +// |
| 125 | +// The default CDI directory configuration is chosen to encourage |
| 126 | +// separating dynamically generated CDI Spec files from static ones. |
| 127 | +// The default directories are '/etc/cdi' and '/var/run/cdi'. By putting |
| 128 | +// dynamically generated Spec files under '/var/run/cdi', those take |
| 129 | +// precedence over static ones in '/etc/cdi'. |
| 130 | +package cdi |
0 commit comments