mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2024-11-25 05:21:33 +00:00
Refactor accepting device lists from volume mounts as a boolean
Also hard code the "root" path where these volume mounts will be looked for rather than making it configurable. Signed-off-by: Kevin Klues <kklues@nvidia.com>
This commit is contained in:
parent
928905ce94
commit
7c00385797
@ -1,7 +1,7 @@
|
|||||||
disable-require = false
|
disable-require = false
|
||||||
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
||||||
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
||||||
#look-for-nvidia-visible-devices-as-volume-mounts-under = "/var/run/nvidia-container-devices"
|
#accept-nvidia-visible-devices-as-volume-mounts = false
|
||||||
|
|
||||||
[nvidia-container-cli]
|
[nvidia-container-cli]
|
||||||
#root = "/run/nvidia/driver"
|
#root = "/run/nvidia/driver"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
disable-require = false
|
disable-require = false
|
||||||
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
||||||
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
||||||
#look-for-nvidia-visible-devices-as-volume-mounts-under = "/var/run/nvidia-container-devices"
|
#accept-nvidia-visible-devices-as-volume-mounts = false
|
||||||
|
|
||||||
[nvidia-container-cli]
|
[nvidia-container-cli]
|
||||||
#root = "/run/nvidia/driver"
|
#root = "/run/nvidia/driver"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
disable-require = false
|
disable-require = false
|
||||||
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
||||||
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
||||||
#look-for-nvidia-visible-devices-as-volume-mounts-under = "/var/run/nvidia-container-devices"
|
#accept-nvidia-visible-devices-as-volume-mounts = false
|
||||||
|
|
||||||
[nvidia-container-cli]
|
[nvidia-container-cli]
|
||||||
#root = "/run/nvidia/driver"
|
#root = "/run/nvidia/driver"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
disable-require = false
|
disable-require = false
|
||||||
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
||||||
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
||||||
#look-for-nvidia-visible-devices-as-volume-mounts-under = "/var/run/nvidia-container-devices"
|
#accept-nvidia-visible-devices-as-volume-mounts = false
|
||||||
|
|
||||||
[nvidia-container-cli]
|
[nvidia-container-cli]
|
||||||
#root = "/run/nvidia/driver"
|
#root = "/run/nvidia/driver"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
disable-require = false
|
disable-require = false
|
||||||
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
||||||
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
||||||
#look-for-nvidia-visible-devices-as-volume-mounts-under = "/var/run/nvidia-container-devices"
|
#accept-nvidia-visible-devices-as-volume-mounts = false
|
||||||
|
|
||||||
[nvidia-container-cli]
|
[nvidia-container-cli]
|
||||||
#root = "/run/nvidia/driver"
|
#root = "/run/nvidia/driver"
|
||||||
|
@ -35,6 +35,10 @@ const (
|
|||||||
capSysAdmin = "CAP_SYS_ADMIN"
|
capSysAdmin = "CAP_SYS_ADMIN"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
deviceListAsVolumeMountsRoot = "/var/run/nvidia-container-devices"
|
||||||
|
)
|
||||||
|
|
||||||
type nvidiaConfig struct {
|
type nvidiaConfig struct {
|
||||||
Devices string
|
Devices string
|
||||||
MigConfigDevices string
|
MigConfigDevices string
|
||||||
@ -236,10 +240,10 @@ func getDevicesFromEnvvar(env map[string]string, legacyImage bool) *string {
|
|||||||
return devices
|
return devices
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDevicesFromMounts(root string, mounts []Mount) *string {
|
func getDevicesFromMounts(mounts []Mount) *string {
|
||||||
var devices []string
|
var devices []string
|
||||||
for _, m := range mounts {
|
for _, m := range mounts {
|
||||||
root := filepath.Clean(root)
|
root := filepath.Clean(deviceListAsVolumeMountsRoot)
|
||||||
source := filepath.Clean(m.Source)
|
source := filepath.Clean(m.Source)
|
||||||
destination := filepath.Clean(m.Destination)
|
destination := filepath.Clean(m.Destination)
|
||||||
|
|
||||||
@ -274,14 +278,16 @@ func getDevicesFromMounts(root string, mounts []Mount) *string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getDevices(hookConfig *HookConfig, env map[string]string, mounts []Mount, privileged bool, legacyImage bool) *string {
|
func getDevices(hookConfig *HookConfig, env map[string]string, mounts []Mount, privileged bool, legacyImage bool) *string {
|
||||||
// Try and get the device list from mount volumes first
|
// If enabled, try and get the device list from volume mounts first
|
||||||
devices := getDevicesFromMounts(*hookConfig.DeviceListVolumeMount, mounts)
|
if hookConfig.AcceptDeviceListAsVolumeMounts {
|
||||||
if devices != nil {
|
devices := getDevicesFromMounts(mounts)
|
||||||
return devices
|
if devices != nil {
|
||||||
|
return devices
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to reading from the environment variable if privileges are correct
|
// Fallback to reading from the environment variable if privileges are correct
|
||||||
devices = getDevicesFromEnvvar(env, legacyImage)
|
devices := getDevicesFromEnvvar(env, legacyImage)
|
||||||
if devices == nil {
|
if devices == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -454,30 +454,26 @@ func TestGetNvidiaConfig(t *testing.T) {
|
|||||||
func TestGetDevicesFromMounts(t *testing.T) {
|
func TestGetDevicesFromMounts(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
description string
|
description string
|
||||||
root string
|
|
||||||
mounts []Mount
|
mounts []Mount
|
||||||
expectedDevices *string
|
expectedDevices *string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
description: "No mounts",
|
description: "No mounts",
|
||||||
root: defaultDeviceListVolumeMount,
|
|
||||||
mounts: nil,
|
mounts: nil,
|
||||||
expectedDevices: nil,
|
expectedDevices: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Host path is not /dev/null",
|
description: "Host path is not /dev/null",
|
||||||
root: defaultDeviceListVolumeMount,
|
|
||||||
mounts: []Mount{
|
mounts: []Mount{
|
||||||
{
|
{
|
||||||
Source: "/not/dev/null",
|
Source: "/not/dev/null",
|
||||||
Destination: filepath.Join(defaultDeviceListVolumeMount, "GPU0"),
|
Destination: filepath.Join(deviceListAsVolumeMountsRoot, "GPU0"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedDevices: nil,
|
expectedDevices: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Container path is not prefixed by 'root'",
|
description: "Container path is not prefixed by 'root'",
|
||||||
root: defaultDeviceListVolumeMount,
|
|
||||||
mounts: []Mount{
|
mounts: []Mount{
|
||||||
{
|
{
|
||||||
Source: "/dev/null",
|
Source: "/dev/null",
|
||||||
@ -488,41 +484,38 @@ func TestGetDevicesFromMounts(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Container path is only 'root'",
|
description: "Container path is only 'root'",
|
||||||
root: defaultDeviceListVolumeMount,
|
|
||||||
mounts: []Mount{
|
mounts: []Mount{
|
||||||
{
|
{
|
||||||
Source: "/dev/null",
|
Source: "/dev/null",
|
||||||
Destination: defaultDeviceListVolumeMount,
|
Destination: deviceListAsVolumeMountsRoot,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedDevices: nil,
|
expectedDevices: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Discover 2 devices",
|
description: "Discover 2 devices",
|
||||||
root: defaultDeviceListVolumeMount,
|
|
||||||
mounts: []Mount{
|
mounts: []Mount{
|
||||||
{
|
{
|
||||||
Source: "/dev/null",
|
Source: "/dev/null",
|
||||||
Destination: filepath.Join(defaultDeviceListVolumeMount, "GPU0"),
|
Destination: filepath.Join(deviceListAsVolumeMountsRoot, "GPU0"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Source: "/dev/null",
|
Source: "/dev/null",
|
||||||
Destination: filepath.Join(defaultDeviceListVolumeMount, "GPU1"),
|
Destination: filepath.Join(deviceListAsVolumeMountsRoot, "GPU1"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedDevices: &[]string{"GPU0,GPU1"}[0],
|
expectedDevices: &[]string{"GPU0,GPU1"}[0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Discover 2 devices with slashes in the name",
|
description: "Discover 2 devices with slashes in the name",
|
||||||
root: defaultDeviceListVolumeMount,
|
|
||||||
mounts: []Mount{
|
mounts: []Mount{
|
||||||
{
|
{
|
||||||
Source: "/dev/null",
|
Source: "/dev/null",
|
||||||
Destination: filepath.Join(defaultDeviceListVolumeMount, "GPU0-MIG0/0/1"),
|
Destination: filepath.Join(deviceListAsVolumeMountsRoot, "GPU0-MIG0/0/1"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Source: "/dev/null",
|
Source: "/dev/null",
|
||||||
Destination: filepath.Join(defaultDeviceListVolumeMount, "GPU1-MIG0/0/1"),
|
Destination: filepath.Join(deviceListAsVolumeMountsRoot, "GPU1-MIG0/0/1"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedDevices: &[]string{"GPU0-MIG0/0/1,GPU1-MIG0/0/1"}[0],
|
expectedDevices: &[]string{"GPU0-MIG0/0/1,GPU1-MIG0/0/1"}[0],
|
||||||
@ -530,7 +523,7 @@ func TestGetDevicesFromMounts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.description, func(t *testing.T) {
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
devices := getDevicesFromMounts(tc.root, tc.mounts)
|
devices := getDevicesFromMounts(tc.mounts)
|
||||||
if !reflect.DeepEqual(devices, tc.expectedDevices) {
|
if !reflect.DeepEqual(devices, tc.expectedDevices) {
|
||||||
t.Errorf("Unexpected devices (got: %v, wanted: %v)", *devices, *tc.expectedDevices)
|
t.Errorf("Unexpected devices (got: %v, wanted: %v)", *devices, *tc.expectedDevices)
|
||||||
}
|
}
|
||||||
@ -545,6 +538,7 @@ func TestDeviceListSourcePriority(t *testing.T) {
|
|||||||
envvarDevices string
|
envvarDevices string
|
||||||
privileged bool
|
privileged bool
|
||||||
acceptUnprivileged bool
|
acceptUnprivileged bool
|
||||||
|
acceptMounts bool
|
||||||
expectedDevices *string
|
expectedDevices *string
|
||||||
expectedPanic bool
|
expectedPanic bool
|
||||||
}{
|
}{
|
||||||
@ -553,16 +547,17 @@ func TestDeviceListSourcePriority(t *testing.T) {
|
|||||||
mountDevices: []Mount{
|
mountDevices: []Mount{
|
||||||
{
|
{
|
||||||
Source: "/dev/null",
|
Source: "/dev/null",
|
||||||
Destination: filepath.Join(defaultDeviceListVolumeMount, "GPU0"),
|
Destination: filepath.Join(deviceListAsVolumeMountsRoot, "GPU0"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Source: "/dev/null",
|
Source: "/dev/null",
|
||||||
Destination: filepath.Join(defaultDeviceListVolumeMount, "GPU1"),
|
Destination: filepath.Join(deviceListAsVolumeMountsRoot, "GPU1"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
envvarDevices: "GPU2,GPU3",
|
envvarDevices: "GPU2,GPU3",
|
||||||
privileged: false,
|
privileged: false,
|
||||||
acceptUnprivileged: false,
|
acceptUnprivileged: false,
|
||||||
|
acceptMounts: true,
|
||||||
expectedDevices: &[]string{"GPU0,GPU1"}[0],
|
expectedDevices: &[]string{"GPU0,GPU1"}[0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -571,6 +566,7 @@ func TestDeviceListSourcePriority(t *testing.T) {
|
|||||||
envvarDevices: "GPU0,GPU1",
|
envvarDevices: "GPU0,GPU1",
|
||||||
privileged: false,
|
privileged: false,
|
||||||
acceptUnprivileged: false,
|
acceptUnprivileged: false,
|
||||||
|
acceptMounts: true,
|
||||||
expectedPanic: true,
|
expectedPanic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -579,6 +575,7 @@ func TestDeviceListSourcePriority(t *testing.T) {
|
|||||||
envvarDevices: "GPU0,GPU1",
|
envvarDevices: "GPU0,GPU1",
|
||||||
privileged: true,
|
privileged: true,
|
||||||
acceptUnprivileged: false,
|
acceptUnprivileged: false,
|
||||||
|
acceptMounts: true,
|
||||||
expectedDevices: &[]string{"GPU0,GPU1"}[0],
|
expectedDevices: &[]string{"GPU0,GPU1"}[0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -587,6 +584,7 @@ func TestDeviceListSourcePriority(t *testing.T) {
|
|||||||
envvarDevices: "GPU0,GPU1",
|
envvarDevices: "GPU0,GPU1",
|
||||||
privileged: false,
|
privileged: false,
|
||||||
acceptUnprivileged: true,
|
acceptUnprivileged: true,
|
||||||
|
acceptMounts: true,
|
||||||
expectedDevices: &[]string{"GPU0,GPU1"}[0],
|
expectedDevices: &[]string{"GPU0,GPU1"}[0],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -600,6 +598,7 @@ func TestDeviceListSourcePriority(t *testing.T) {
|
|||||||
}
|
}
|
||||||
hookConfig := getDefaultHookConfig()
|
hookConfig := getDefaultHookConfig()
|
||||||
hookConfig.AcceptEnvvarUnprivileged = tc.acceptUnprivileged
|
hookConfig.AcceptEnvvarUnprivileged = tc.acceptUnprivileged
|
||||||
|
hookConfig.AcceptDeviceListAsVolumeMounts = tc.acceptMounts
|
||||||
devices = getDevices(&hookConfig, env, tc.mountDevices, tc.privileged, false)
|
devices = getDevices(&hookConfig, env, tc.mountDevices, tc.privileged, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,10 +13,6 @@ const (
|
|||||||
driverPath = "/run/nvidia/driver"
|
driverPath = "/run/nvidia/driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
defaultDeviceListVolumeMount = "/var/run/nvidia-container-devices"
|
|
||||||
)
|
|
||||||
|
|
||||||
var defaultPaths = [...]string{
|
var defaultPaths = [...]string{
|
||||||
path.Join(driverPath, configPath),
|
path.Join(driverPath, configPath),
|
||||||
configPath,
|
configPath,
|
||||||
@ -38,20 +34,20 @@ type CLIConfig struct {
|
|||||||
|
|
||||||
// HookConfig : options for the nvidia-container-toolkit.
|
// HookConfig : options for the nvidia-container-toolkit.
|
||||||
type HookConfig struct {
|
type HookConfig struct {
|
||||||
DisableRequire bool `toml:"disable-require"`
|
DisableRequire bool `toml:"disable-require"`
|
||||||
SwarmResource *string `toml:"swarm-resource"`
|
SwarmResource *string `toml:"swarm-resource"`
|
||||||
AcceptEnvvarUnprivileged bool `toml:"accept-nvidia-visible-devices-envvar-when-unprivileged"`
|
AcceptEnvvarUnprivileged bool `toml:"accept-nvidia-visible-devices-envvar-when-unprivileged"`
|
||||||
DeviceListVolumeMount *string `toml:"look-for-nvidia-visible-devices-as-volume-mounts-under"`
|
AcceptDeviceListAsVolumeMounts bool `toml:"accept-nvidia-visible-devices-as-volume-mounts"`
|
||||||
|
|
||||||
NvidiaContainerCLI CLIConfig `toml:"nvidia-container-cli"`
|
NvidiaContainerCLI CLIConfig `toml:"nvidia-container-cli"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultHookConfig() (config HookConfig) {
|
func getDefaultHookConfig() (config HookConfig) {
|
||||||
return HookConfig{
|
return HookConfig{
|
||||||
DisableRequire: false,
|
DisableRequire: false,
|
||||||
SwarmResource: nil,
|
SwarmResource: nil,
|
||||||
AcceptEnvvarUnprivileged: true,
|
AcceptEnvvarUnprivileged: true,
|
||||||
DeviceListVolumeMount: &[]string{defaultDeviceListVolumeMount}[0],
|
AcceptDeviceListAsVolumeMounts: false,
|
||||||
NvidiaContainerCLI: CLIConfig{
|
NvidiaContainerCLI: CLIConfig{
|
||||||
Root: nil,
|
Root: nil,
|
||||||
Path: nil,
|
Path: nil,
|
||||||
|
Loading…
Reference in New Issue
Block a user