2022-11-23 15:29:18 +00:00
/ * *
# Copyright ( c ) NVIDIA CORPORATION . All rights reserved .
#
# 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 generate
import (
"path/filepath"
"github.com/NVIDIA/nvidia-container-toolkit/internal/discover"
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
"github.com/container-orchestrated-devices/container-device-interface/specs-go"
"github.com/sirupsen/logrus"
)
type deviceFolderPermissions struct {
2022-12-01 16:21:14 +00:00
logger * logrus . Logger
root string
folders [ ] string
2022-11-23 15:29:18 +00:00
}
var _ discover . Discover = ( * deviceFolderPermissions ) ( nil )
// NewDeviceFolderPermissionHookDiscoverer creates a discoverer that can be used to update the permissions for the parent folders of nested device nodes from the specified set of device specs.
// This works around an issue with rootless podman when using crun as a low-level runtime.
// See https://github.com/containers/crun/issues/1047
2022-12-01 16:21:14 +00:00
// The nested devices that are applicable to the NVIDIA GPU devices are:
// - DRM devices at /dev/dri/*
// - NVIDIA Caps devices at /dev/nvidia-caps/*
2022-11-23 15:29:18 +00:00
func NewDeviceFolderPermissionHookDiscoverer ( logger * logrus . Logger , root string , deviceSpecs [ ] specs . Device ) ( discover . Discover , error ) {
2022-12-01 16:21:14 +00:00
var folders [ ] string
2022-11-23 15:29:18 +00:00
seen := make ( map [ string ] bool )
for _ , device := range deviceSpecs {
for _ , dn := range device . ContainerEdits . DeviceNodes {
2022-12-01 16:21:14 +00:00
df := filepath . Dir ( dn . Path )
if seen [ df ] {
2022-11-23 15:29:18 +00:00
continue
}
2022-12-01 16:21:14 +00:00
// We only consider the special case paths
if df != "/dev/dri" && df != "/dev/nvidia-caps" {
continue
2022-11-23 15:29:18 +00:00
}
2022-12-01 16:21:14 +00:00
folders = append ( folders , df )
seen [ df ] = true
}
if len ( folders ) == 2 {
break
2022-11-23 15:29:18 +00:00
}
}
2022-12-01 16:21:14 +00:00
if len ( folders ) == 0 {
return discover . None { } , nil
2022-11-23 15:29:18 +00:00
}
d := & deviceFolderPermissions {
2022-12-01 16:21:14 +00:00
logger : logger ,
root : root ,
folders : folders ,
2022-11-23 15:29:18 +00:00
}
return d , nil
}
// Devices are empty for this discoverer
func ( d * deviceFolderPermissions ) Devices ( ) ( [ ] discover . Device , error ) {
return nil , nil
}
2022-12-01 16:21:14 +00:00
// Hooks returns a set of hooks that sets the file mode to 755 of parent folders for nested device nodes.
2022-11-23 15:29:18 +00:00
func ( d * deviceFolderPermissions ) Hooks ( ) ( [ ] discover . Hook , error ) {
2022-12-01 16:21:14 +00:00
if len ( d . folders ) == 0 {
return nil , nil
2022-11-23 15:29:18 +00:00
}
2022-12-01 16:21:14 +00:00
args := [ ] string { "--mode" , "755" }
for _ , folder := range d . folders {
args = append ( args , "--path" , folder )
}
hook := discover . CreateNvidiaCTKHook (
d . logger ,
lookup . NewExecutableLocator ( d . logger , d . root ) ,
nvidiaCTKExecutable ,
nvidiaCTKDefaultFilePath ,
"chmod" ,
args ... ,
)
return [ ] discover . Hook { hook } , nil
2022-11-23 15:29:18 +00:00
}
// Mounts are empty for this discoverer
func ( d * deviceFolderPermissions ) Mounts ( ) ( [ ] discover . Mount , error ) {
return nil , nil
}