| /** |
| # 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 createdevicenodes |
| |
| import ( |
| "fmt" |
| |
| "github.com/urfave/cli/v2" |
| |
| "github.com/NVIDIA/nvidia-container-toolkit/internal/logger" |
| "github.com/NVIDIA/nvidia-container-toolkit/internal/system/nvdevices" |
| "github.com/NVIDIA/nvidia-container-toolkit/internal/system/nvmodules" |
| ) |
| |
| type command struct { |
| logger logger.Interface |
| } |
| |
| type options struct { |
| root string |
| devRoot string |
| |
| dryRun bool |
| |
| control bool |
| |
| loadKernelModules bool |
| } |
| |
| // NewCommand constructs a command sub-command with the specified logger |
| func NewCommand(logger logger.Interface) *cli.Command { |
| c := command{ |
| logger: logger, |
| } |
| return c.build() |
| } |
| |
| // build |
| func (m command) build() *cli.Command { |
| opts := options{} |
| |
| c := cli.Command{ |
| Name: "create-device-nodes", |
| Usage: "A utility to create NVIDIA device nodes", |
| Before: func(c *cli.Context) error { |
| return m.validateFlags(c, &opts) |
| }, |
| Action: func(c *cli.Context) error { |
| return m.run(c, &opts) |
| }, |
| } |
| |
| c.Flags = []cli.Flag{ |
| &cli.StringFlag{ |
| Name: "root", |
| // TODO: Remove this alias |
| Aliases: []string{"driver-root"}, |
| Usage: "the path to to the root to use to load the kernel modules. This root must be a chrootable path. " + |
| "If device nodes to be created these will be created at `ROOT`/dev unless an alternative path is specified", |
| Value: "/", |
| Destination: &opts.root, |
| // TODO: Remove the NVIDIA_DRIVER_ROOT and DRIVER_ROOT envvars. |
| EnvVars: []string{"ROOT", "NVIDIA_DRIVER_ROOT", "DRIVER_ROOT"}, |
| }, |
| &cli.StringFlag{ |
| Name: "dev-root", |
| Usage: "specify the root where `/dev` is located. If this is not specified, the root is assumed.", |
| Destination: &opts.devRoot, |
| EnvVars: []string{"NVIDIA_DEV_ROOT", "DEV_ROOT"}, |
| }, |
| &cli.BoolFlag{ |
| Name: "control-devices", |
| Usage: "create all control device nodes: nvidiactl, nvidia-modeset, nvidia-uvm, nvidia-uvm-tools", |
| Destination: &opts.control, |
| }, |
| &cli.BoolFlag{ |
| Name: "load-kernel-modules", |
| Usage: "load the NVIDIA Kernel Modules before creating devices nodes", |
| Destination: &opts.loadKernelModules, |
| }, |
| &cli.BoolFlag{ |
| Name: "dry-run", |
| Usage: "if set, the command will not perform any operations", |
| Value: false, |
| Destination: &opts.dryRun, |
| EnvVars: []string{"DRY_RUN"}, |
| }, |
| } |
| |
| return &c |
| } |
| |
| func (m command) validateFlags(r *cli.Context, opts *options) error { |
| if opts.devRoot == "" && opts.root != "" { |
| m.logger.Infof("Using dev-root %q", opts.root) |
| opts.devRoot = opts.root |
| } |
| return nil |
| } |
| |
| func (m command) run(c *cli.Context, opts *options) error { |
| if opts.loadKernelModules { |
| modules := nvmodules.New( |
| nvmodules.WithLogger(m.logger), |
| nvmodules.WithDryRun(opts.dryRun), |
| nvmodules.WithRoot(opts.root), |
| ) |
| if err := modules.LoadAll(); err != nil { |
| return fmt.Errorf("failed to load NVIDIA kernel modules: %v", err) |
| } |
| } |
| |
| if opts.control { |
| devices, err := nvdevices.New( |
| nvdevices.WithLogger(m.logger), |
| nvdevices.WithDryRun(opts.dryRun), |
| nvdevices.WithDevRoot(opts.devRoot), |
| ) |
| if err != nil { |
| return err |
| } |
| m.logger.Infof("Creating control device nodes at %s", opts.devRoot) |
| if err := devices.CreateNVIDIAControlDevices(); err != nil { |
| return fmt.Errorf("failed to create NVIDIA control device nodes: %v", err) |
| } |
| } |
| return nil |
| } |