1
2
3
4 package devices
5
6 import (
7 "context"
8 "fmt"
9
10 "github.com/Microsoft/go-winio/pkg/guid"
11 "github.com/Microsoft/hcsshim/internal/cmd"
12 "github.com/Microsoft/hcsshim/internal/guestpath"
13 "github.com/Microsoft/hcsshim/internal/log"
14 "github.com/Microsoft/hcsshim/internal/resources"
15 "github.com/Microsoft/hcsshim/internal/uvm"
16 )
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 func InstallDrivers(ctx context.Context, vm *uvm.UtilityVM, share string, gpuDriver bool) (closer resources.ResourceCloser, err error) {
32 defer func() {
33 if err != nil && closer != nil {
34
35 if releaseErr := closer.Release(ctx); releaseErr != nil {
36 log.G(ctx).WithError(releaseErr).Error("failed to release container resource")
37 }
38 closer = nil
39 }
40 }()
41 if vm.OS() == "windows" {
42 options := vm.DefaultVSMBOptions(true)
43 closer, err = vm.AddVSMB(ctx, share, options)
44 if err != nil {
45 return closer, fmt.Errorf("failed to add VSMB share to utility VM for path %+v: %s", share, err)
46 }
47 uvmPath, err := vm.GetVSMBUvmPath(ctx, share, true)
48 if err != nil {
49 return closer, err
50 }
51
52
53 return closer, execPnPInstallDriver(ctx, vm, uvmPath)
54 }
55
56
57 uvmPathForShare := fmt.Sprintf(guestpath.LCOWGlobalMountPrefixFmt, vm.UVMMountCounter())
58 mount, err := vm.AddSCSI(ctx,
59 share,
60 uvmPathForShare,
61 true,
62 false,
63 []string{},
64 uvm.VMAccessTypeIndividual)
65 if err != nil {
66 return closer, fmt.Errorf("failed to add SCSI disk to utility VM for path %+v: %s", share, err)
67 }
68 closer = mount
69 uvmPathForShare = mount.UVMPath
70
71
72
73
74 ns := guid.GUID{Data1: 0x914aadc8, Data2: 0xf700, Data3: 0x4365, Data4: [8]byte{0x80, 0x16, 0xdd, 0xad, 0x0a, 0x9d, 0x40, 0x6d}}
75 driverGUID, err := guid.NewV5(ns, []byte(share))
76 if err != nil {
77 return closer, fmt.Errorf("failed to create a guid path for driver %+v: %s", share, err)
78 }
79 uvmReadWritePath := fmt.Sprintf(guestpath.LCOWGlobalDriverPrefixFmt, driverGUID.String())
80 if gpuDriver {
81
82 uvmReadWritePath = guestpath.LCOWNvidiaMountPath
83 }
84
85
86 return closer, execGCSInstallDriver(ctx, vm, uvmPathForShare, uvmReadWritePath)
87 }
88
89 func execGCSInstallDriver(ctx context.Context, vm *uvm.UtilityVM, driverDir string, driverReadWriteDir string) error {
90 p, l, err := cmd.CreateNamedPipeListener()
91 if err != nil {
92 return err
93 }
94 defer l.Close()
95
96 var stderrOutput string
97 errChan := make(chan error)
98
99 go readAllPipeOutput(l, errChan, &stderrOutput)
100
101 args := []string{
102 "/bin/install-drivers",
103 driverReadWriteDir,
104 driverDir,
105 }
106 req := &cmd.CmdProcessRequest{
107 Args: args,
108 Stderr: p,
109 }
110
111
112
113
114
115
116
117
118 exitCode, execErr := cmd.ExecInUvm(ctx, vm, req)
119
120
121 select {
122 case err := <-errChan:
123 if err != nil && err != noExecOutputErr {
124 return fmt.Errorf("failed to get stderr output from command %s: %v", driverDir, err)
125 }
126 case <-ctx.Done():
127 return fmt.Errorf("timed out waiting for the console output from installing driver %s: %v", driverDir, ctx.Err())
128 }
129
130 if execErr != nil {
131 return fmt.Errorf("%v: failed to install driver %s in uvm with exit code %d: %v", execErr, driverDir, exitCode, stderrOutput)
132 }
133 return nil
134 }
135
View as plain text