1
2
3
4 package devices
5
6 import (
7 "context"
8 "fmt"
9
10 "github.com/Microsoft/hcsshim/internal/cmd"
11 "github.com/Microsoft/hcsshim/internal/log"
12 "github.com/Microsoft/hcsshim/internal/uvm"
13 "github.com/pkg/errors"
14 )
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 func AddDevice(ctx context.Context, vm *uvm.UtilityVM, idType, deviceID string, index uint16, deviceUtilPath string) (vpci *uvm.VPCIDevice, locationPaths []string, err error) {
32 defer func() {
33 if err != nil && vpci != nil {
34
35 if releaseErr := vpci.Release(ctx); releaseErr != nil {
36 log.G(ctx).WithError(releaseErr).Error("failed to release container resource")
37 }
38 vpci = nil
39 }
40 }()
41 if idType == uvm.VPCIDeviceIDType || idType == uvm.VPCIDeviceIDTypeLegacy {
42 vpci, err = vm.AssignDevice(ctx, deviceID, index, "")
43 if err != nil {
44 return vpci, nil, errors.Wrapf(err, "failed to assign device %s of type %s to pod %s", deviceID, idType, vm.ID())
45 }
46 vmBusInstanceID := vm.GetAssignedDeviceVMBUSInstanceID(vpci.VMBusGUID)
47 log.G(ctx).WithField("vmbus id", vmBusInstanceID).Info("vmbus instance ID")
48
49 locationPaths, err = getChildrenDeviceLocationPaths(ctx, vm, vmBusInstanceID, deviceUtilPath)
50 return vpci, locationPaths, err
51 }
52
53 return vpci, nil, fmt.Errorf("device type %s for device %s is not supported in windows", idType, deviceID)
54 }
55
56
57
58
59 func getChildrenDeviceLocationPaths(ctx context.Context, vm *uvm.UtilityVM, vmBusInstanceID string, deviceUtilPath string) ([]string, error) {
60 p, l, err := cmd.CreateNamedPipeListener()
61 if err != nil {
62 return nil, err
63 }
64 defer l.Close()
65
66 var pipeResults []string
67 errChan := make(chan error)
68
69 go readCsPipeOutput(l, errChan, &pipeResults)
70
71 args := createDeviceUtilChildrenCommand(deviceUtilPath, vmBusInstanceID)
72 cmdReq := &cmd.CmdProcessRequest{
73 Args: args,
74 Stdout: p,
75 }
76 exitCode, err := cmd.ExecInUvm(ctx, vm, cmdReq)
77 if err != nil {
78 return nil, errors.Wrapf(err, "failed to find devices with exit code %d", exitCode)
79 }
80
81
82 select {
83 case err := <-errChan:
84 if err != nil {
85 return nil, err
86 }
87 case <-ctx.Done():
88 return nil, ctx.Err()
89 }
90
91 return pipeResults, nil
92 }
93
94
95
96
97
98
99
100
101
102
103 func createDeviceUtilChildrenCommand(deviceUtilPath string, vmBusInstanceID string) []string {
104 parentIDsFlag := fmt.Sprintf("--parentID=%s", vmBusInstanceID)
105 args := []string{deviceUtilPath, "children", parentIDsFlag, "--property=location"}
106 return args
107 }
108
View as plain text