2022-02-28 12:32:27 +00:00
|
|
|
/*
|
|
|
|
Copyright © 2021 The CDI Authors
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package cdi
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
|
2022-06-20 15:02:34 +00:00
|
|
|
cdi "github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
2022-02-28 12:32:27 +00:00
|
|
|
oci "github.com/opencontainers/runtime-spec/specs-go"
|
|
|
|
)
|
|
|
|
|
|
|
|
//
|
|
|
|
// Registry keeps a cache of all CDI Specs installed or generated on
|
|
|
|
// the host. Registry is the primary interface clients should use to
|
|
|
|
// interact with CDI.
|
|
|
|
//
|
|
|
|
// The most commonly used Registry functions are for refreshing the
|
|
|
|
// registry and injecting CDI devices into an OCI Spec.
|
|
|
|
//
|
|
|
|
type Registry interface {
|
|
|
|
RegistryResolver
|
|
|
|
RegistryRefresher
|
|
|
|
DeviceDB() RegistryDeviceDB
|
|
|
|
SpecDB() RegistrySpecDB
|
|
|
|
}
|
|
|
|
|
|
|
|
// RegistryRefresher is the registry interface for refreshing the
|
|
|
|
// cache of CDI Specs and devices.
|
|
|
|
//
|
2022-06-20 15:02:34 +00:00
|
|
|
// Configure reconfigures the registry with the given options.
|
|
|
|
//
|
2022-02-28 12:32:27 +00:00
|
|
|
// Refresh rescans all CDI Spec directories and updates the
|
|
|
|
// state of the cache to reflect any changes. It returns any
|
|
|
|
// errors encountered during the refresh.
|
|
|
|
//
|
|
|
|
// GetErrors returns all errors encountered for any of the scanned
|
|
|
|
// Spec files during the last cache refresh.
|
|
|
|
//
|
|
|
|
// GetSpecDirectories returns the set up CDI Spec directories
|
|
|
|
// currently in use. The directories are returned in the scan
|
|
|
|
// order of Refresh().
|
2022-06-20 15:02:34 +00:00
|
|
|
//
|
|
|
|
// GetSpecDirErrors returns any errors related to the configured
|
|
|
|
// Spec directories.
|
2022-02-28 12:32:27 +00:00
|
|
|
type RegistryRefresher interface {
|
2022-06-20 15:02:34 +00:00
|
|
|
Configure(...Option) error
|
2022-02-28 12:32:27 +00:00
|
|
|
Refresh() error
|
|
|
|
GetErrors() map[string][]error
|
|
|
|
GetSpecDirectories() []string
|
2022-06-20 15:02:34 +00:00
|
|
|
GetSpecDirErrors() map[string]error
|
2022-02-28 12:32:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// RegistryResolver is the registry interface for injecting CDI
|
|
|
|
// devices into an OCI Spec.
|
|
|
|
//
|
|
|
|
// InjectDevices takes an OCI Spec and injects into it a set of
|
|
|
|
// CDI devices given by qualified name. It returns the names of
|
|
|
|
// any unresolved devices and an error if injection fails.
|
|
|
|
type RegistryResolver interface {
|
|
|
|
InjectDevices(spec *oci.Spec, device ...string) (unresolved []string, err error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// RegistryDeviceDB is the registry interface for querying devices.
|
|
|
|
//
|
|
|
|
// GetDevice returns the CDI device for the given qualified name. If
|
|
|
|
// the device is not GetDevice returns nil.
|
|
|
|
//
|
|
|
|
// ListDevices returns a slice with the names of qualified device
|
|
|
|
// known. The returned slice is sorted.
|
|
|
|
type RegistryDeviceDB interface {
|
|
|
|
GetDevice(device string) *Device
|
|
|
|
ListDevices() []string
|
|
|
|
}
|
|
|
|
|
|
|
|
// RegistrySpecDB is the registry interface for querying CDI Specs.
|
|
|
|
//
|
|
|
|
// ListVendors returns a slice with all vendors known. The returned
|
|
|
|
// slice is sorted.
|
|
|
|
//
|
|
|
|
// ListClasses returns a slice with all classes known. The returned
|
|
|
|
// slice is sorted.
|
|
|
|
//
|
|
|
|
// GetVendorSpecs returns a slice of all Specs for the vendor.
|
|
|
|
//
|
|
|
|
// GetSpecErrors returns any errors for the Spec encountered during
|
|
|
|
// the last cache refresh.
|
2022-06-20 15:02:34 +00:00
|
|
|
//
|
|
|
|
// WriteSpec writes the Spec with the given content and name to the
|
|
|
|
// last Spec directory.
|
2022-02-28 12:32:27 +00:00
|
|
|
type RegistrySpecDB interface {
|
|
|
|
ListVendors() []string
|
|
|
|
ListClasses() []string
|
|
|
|
GetVendorSpecs(vendor string) []*Spec
|
|
|
|
GetSpecErrors(*Spec) []error
|
2022-06-20 15:02:34 +00:00
|
|
|
WriteSpec(raw *cdi.Spec, name string) error
|
2022-02-28 12:32:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type registry struct {
|
|
|
|
*Cache
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ Registry = ®istry{}
|
|
|
|
|
|
|
|
var (
|
|
|
|
reg *registry
|
|
|
|
initOnce sync.Once
|
|
|
|
)
|
|
|
|
|
|
|
|
// GetRegistry returns the CDI registry. If any options are given, those
|
|
|
|
// are applied to the registry.
|
|
|
|
func GetRegistry(options ...Option) Registry {
|
|
|
|
var new bool
|
|
|
|
initOnce.Do(func() {
|
|
|
|
reg, _ = getRegistry(options...)
|
|
|
|
new = true
|
|
|
|
})
|
|
|
|
if !new && len(options) > 0 {
|
|
|
|
reg.Configure(options...)
|
|
|
|
reg.Refresh()
|
|
|
|
}
|
|
|
|
return reg
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeviceDB returns the registry interface for querying devices.
|
|
|
|
func (r *registry) DeviceDB() RegistryDeviceDB {
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
// SpecDB returns the registry interface for querying Specs.
|
|
|
|
func (r *registry) SpecDB() RegistrySpecDB {
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func getRegistry(options ...Option) (*registry, error) {
|
|
|
|
c, err := NewCache(options...)
|
|
|
|
return ®istry{c}, err
|
|
|
|
}
|