...

Source file src/github.com/Microsoft/hcsshim/cmd/gcstools/installdrivers.go

Documentation: github.com/Microsoft/hcsshim/cmd/gcstools

     1  //go:build linux
     2  // +build linux
     3  
     4  package main
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"io/fs"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"strings"
    14  
    15  	"github.com/Microsoft/hcsshim/internal/guest/storage/overlay"
    16  	"github.com/Microsoft/hcsshim/internal/log"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  const moduleExtension = ".ko"
    21  
    22  func install(ctx context.Context) error {
    23  	args := []string(os.Args[1:])
    24  
    25  	if len(args) != 2 {
    26  		return fmt.Errorf("expected two args, instead got %v", len(args))
    27  	}
    28  	targetOverlayPath := args[0]
    29  	driver := args[1]
    30  
    31  	if _, err := os.Lstat(targetOverlayPath); err == nil {
    32  		// We assume the overlay path to be unique per set of drivers. Thus, if the path
    33  		// exists already, we have already installed these drivers, and can quit early.
    34  		return nil
    35  	} else if !errors.Is(err, fs.ErrNotExist) {
    36  		return fmt.Errorf("failed to stat overlay dir: %s: %w", targetOverlayPath, err)
    37  	}
    38  
    39  	// create an overlay mount from the driver's UVM path so we can write to the
    40  	// mount path in the UVM despite having mounted in the driver originally as
    41  	// readonly
    42  	upperPath := filepath.Join(targetOverlayPath, "upper")
    43  	workPath := filepath.Join(targetOverlayPath, "work")
    44  	rootPath := filepath.Join(targetOverlayPath, "content")
    45  	if err := overlay.Mount(ctx, []string{driver}, upperPath, workPath, rootPath, false); err != nil {
    46  		return err
    47  	}
    48  
    49  	// find all module files, which end with ".ko" extension, and remove extension
    50  	// for use when calling `modprobe` below.
    51  	modules := []string{}
    52  	if walkErr := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {
    53  		if err != nil {
    54  			return errors.Wrap(err, "failed to read directory while walking dir")
    55  		}
    56  		if !info.IsDir() && filepath.Ext(info.Name()) == moduleExtension {
    57  			moduleName := strings.TrimSuffix(info.Name(), moduleExtension)
    58  			modules = append(modules, moduleName)
    59  		}
    60  		return nil
    61  	}); walkErr != nil {
    62  		return walkErr
    63  	}
    64  
    65  	// create a new module dependency map database for the driver
    66  	depmodArgs := []string{"-b", rootPath}
    67  	cmd := exec.Command("depmod", depmodArgs...)
    68  	out, err := cmd.CombinedOutput()
    69  	if err != nil {
    70  		return errors.Wrapf(err, "failed to run depmod with args %v: %s", depmodArgs, out)
    71  	}
    72  
    73  	// run modprobe for every module name found
    74  	modprobeArgs := append([]string{"-d", rootPath, "-a"}, modules...)
    75  	cmd = exec.Command(
    76  		"modprobe",
    77  		modprobeArgs...,
    78  	)
    79  
    80  	out, err = cmd.CombinedOutput()
    81  	if err != nil {
    82  		return errors.Wrapf(err, "failed to run modprobe with args %v: %s", modprobeArgs, out)
    83  	}
    84  
    85  	return nil
    86  }
    87  
    88  func installDriversMain() {
    89  	ctx := context.Background()
    90  	log.G(ctx).Logger.SetOutput(os.Stderr)
    91  	if err := install(ctx); err != nil {
    92  		log.G(ctx).Fatalf("error while installing drivers: %s", err)
    93  	}
    94  }
    95  

View as plain text