diff --git a/README.md b/README.md index 2e79983..49c2b8b 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,8 @@ Usage of generic-device-plugin: A "count" can be specified to allow a discovered device group to be scheduled multiple times. For example, to permit allocation of the FUSE device 10 times: {"name": "fuse", "groups": [{"count": 10, "paths": [{"path": "/dev/fuse"}]}]} Note: if omitted, "count" is assumed to be 1 + If mountPath is a directory, the device will be mounted to the directory with the name of the device. + For example, to expose the serial devices to the /dev/serial directory: {"name": "serial", "groups": [{"paths": [{"path": "/dev/ttyUSB*", "mountPath": "/dev/serial/"}]}]} --domain string The domain to use when when declaring devices. (default "squat.ai") --listen string The address at which to listen for health and metrics. (default ":8080") --log-level string Log level to use. Possible values: all, debug, info, warn, error, none (default "info") diff --git a/config.go b/config.go index d695313..4903c06 100644 --- a/config.go +++ b/config.go @@ -46,7 +46,9 @@ For example, to allocate and mount an audio capture device: {"name": "capture", For example, to expose a CH340 serial converter: {"name": "ch340", "groups": [{"usb": [{"vendor": "1a86", "product": "7523"}]}]} A "count" can be specified to allow a discovered device group to be scheduled multiple times. For example, to permit allocation of the FUSE device 10 times: {"name": "fuse", "groups": [{"count": 10, "paths": [{"path": "/dev/fuse"}]}]} -Note: if omitted, "count" is assumed to be 1`) +Note: if omitted, "count" is assumed to be 1 +If mountPath is a directory, the device will be mounted to the directory with the name of the device. +For example, to expose the serial devices to the /dev/serial directory: {"name": "serial", "groups": [{"paths": [{"path": "/dev/ttyUSB*", "mountPath": "/dev/serial/"}]}]}`) flag.String("plugin-directory", v1beta1.DevicePluginPath, "The directory in which to create plugin sockets.") flag.String("log-level", logLevelInfo, fmt.Sprintf("Log level to use. Possible values: %s", availableLogLevels)) flag.String("listen", ":8080", "The address at which to listen for health and metrics.") diff --git a/deviceplugin/path.go b/deviceplugin/path.go index 2a29e9a..1124435 100644 --- a/deviceplugin/path.go +++ b/deviceplugin/path.go @@ -18,8 +18,10 @@ import ( "crypto/sha1" "fmt" "io/fs" + "path/filepath" "sort" "strconv" + "strings" "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1" ) @@ -107,6 +109,9 @@ func (gp *GenericPlugin) discoverPath() ([]device, error) { if mountPath == "" { mountPath = paths[k][i] } + if strings.HasSuffix(mountPath, "/") { + mountPath = mountPath + filepath.Base(paths[k][i]) + } switch path.Type { case DevicePathType: d.deviceSpecs = append(d.deviceSpecs, &v1beta1.DeviceSpec{ diff --git a/deviceplugin/path_test.go b/deviceplugin/path_test.go index a4d07a4..c9f10fd 100644 --- a/deviceplugin/path_test.go +++ b/deviceplugin/path_test.go @@ -121,6 +121,63 @@ func TestDiscoverPaths(t *testing.T) { }, err: nil, }, + { + name: "multiple with mount directory", + ds: &DeviceSpec{ + Name: "serial", + Groups: []*Group{ + { + Paths: []*Path{ + { + Path: "/dev/ttyUSB*", + MountPath: "/dev/serial/", + }, + }, + }, + }, + }, + fs: fstest.MapFS{ + "dev/ttyUSB0": {}, + "dev/ttyUSB1": {}, + "dev/ttyUSB2": {}, + "dev/ttyUSB3": {}, + }, + out: []device{ + { + deviceSpecs: []*v1beta1.DeviceSpec{ + { + ContainerPath: "/dev/serial/ttyUSB0", + HostPath: "/dev/ttyUSB0", + }, + }, + }, + { + deviceSpecs: []*v1beta1.DeviceSpec{ + { + ContainerPath: "/dev/serial/ttyUSB1", + HostPath: "/dev/ttyUSB1", + }, + }, + }, + { + deviceSpecs: []*v1beta1.DeviceSpec{ + { + ContainerPath: "/dev/serial/ttyUSB2", + HostPath: "/dev/ttyUSB2", + }, + }, + }, + { + deviceSpecs: []*v1beta1.DeviceSpec{ + { + ContainerPath: "/dev/serial/ttyUSB3", + HostPath: "/dev/ttyUSB3", + }, + }, + }, + }, + err: nil, + }, { name: "only one exists", ds: &DeviceSpec{