1
2
3
4 package hcsv2
5
6 import (
7 "context"
8 "os"
9 "path/filepath"
10 "strings"
11
12 oci "github.com/opencontainers/runtime-spec/specs-go"
13 "github.com/pkg/errors"
14 "go.opencensus.io/trace"
15 "golang.org/x/sys/unix"
16
17 specInternal "github.com/Microsoft/hcsshim/internal/guest/spec"
18 "github.com/Microsoft/hcsshim/internal/guestpath"
19 "github.com/Microsoft/hcsshim/internal/hooks"
20 "github.com/Microsoft/hcsshim/internal/oc"
21 "github.com/Microsoft/hcsshim/pkg/annotations"
22 )
23
24
25
26
27
28 func mkdirAllModePerm(target string) error {
29 savedUmask := unix.Umask(0)
30 defer unix.Umask(savedUmask)
31 return os.MkdirAll(target, os.ModePerm)
32 }
33
34 func updateSandboxMounts(sbid string, spec *oci.Spec) error {
35 for i, m := range spec.Mounts {
36 if strings.HasPrefix(m.Source, guestpath.SandboxMountPrefix) {
37 sandboxSource := specInternal.SandboxMountSource(sbid, m.Source)
38
39
40
41 if !strings.HasPrefix(sandboxSource, specInternal.SandboxMountsDir(sbid)) {
42 return errors.Errorf("mount path %v for mount %v is not within sandbox's mounts dir", sandboxSource, m.Source)
43 }
44
45 spec.Mounts[i].Source = sandboxSource
46
47 _, err := os.Stat(sandboxSource)
48 if os.IsNotExist(err) {
49 if err := mkdirAllModePerm(sandboxSource); err != nil {
50 return err
51 }
52 }
53 }
54 }
55 return nil
56 }
57
58 func updateHugePageMounts(sbid string, spec *oci.Spec) error {
59 for i, m := range spec.Mounts {
60 if strings.HasPrefix(m.Source, guestpath.HugePagesMountPrefix) {
61 mountsDir := specInternal.HugePagesMountsDir(sbid)
62 subPath := strings.TrimPrefix(m.Source, guestpath.HugePagesMountPrefix)
63 pageSize := strings.Split(subPath, string(os.PathSeparator))[0]
64 hugePageMountSource := filepath.Join(mountsDir, subPath)
65
66
67
68 if !strings.HasPrefix(hugePageMountSource, mountsDir) {
69 return errors.Errorf("mount path %v for mount %v is not within hugepages's mounts dir", hugePageMountSource, m.Source)
70 }
71
72 spec.Mounts[i].Source = hugePageMountSource
73
74 _, err := os.Stat(hugePageMountSource)
75 if os.IsNotExist(err) {
76 if err := mkdirAllModePerm(hugePageMountSource); err != nil {
77 return err
78 }
79 if err := unix.Mount("none", hugePageMountSource, "hugetlbfs", 0, "pagesize="+pageSize); err != nil {
80 return errors.Errorf("mount operation failed for %v failed with error %v", hugePageMountSource, err)
81 }
82 }
83 }
84 }
85 return nil
86 }
87
88 func specHasGPUDevice(spec *oci.Spec) bool {
89 for _, d := range spec.Windows.Devices {
90 if d.IDType == "gpu" {
91 return true
92 }
93 }
94 return false
95 }
96
97 func setupWorkloadContainerSpec(ctx context.Context, sbid, id string, spec *oci.Spec) (err error) {
98 ctx, span := oc.StartSpan(ctx, "hcsv2::setupWorkloadContainerSpec")
99 defer span.End()
100 defer func() { oc.SetSpanStatus(span, err) }()
101 span.AddAttributes(
102 trace.StringAttribute("sandboxID", sbid),
103 trace.StringAttribute("cid", id))
104
105
106 if spec.Hostname != "" {
107 return errors.Errorf("workload container must not change hostname: %s", spec.Hostname)
108 }
109
110
111 if err = updateSandboxMounts(sbid, spec); err != nil {
112 return errors.Wrapf(err, "failed to update sandbox mounts for container %v in sandbox %v", id, sbid)
113 }
114
115 if err = updateHugePageMounts(sbid, spec); err != nil {
116 return errors.Wrapf(err, "failed to update hugepages mounts for container %v in sandbox %v", id, sbid)
117 }
118
119
120
121 networkingMounts := specInternal.GenerateWorkloadContainerNetworkMounts(sbid, spec)
122 spec.Mounts = append(spec.Mounts, networkingMounts...)
123
124
125
126
127
128 if err := applyAnnotationsToSpec(ctx, spec); err != nil {
129 return err
130 }
131
132 if rlimCore := spec.Annotations[annotations.RLimitCore]; rlimCore != "" {
133 if err := setCoreRLimit(spec, rlimCore); err != nil {
134 return err
135 }
136 }
137
138
139
140
141
142 if spec.Process.User.Username != "" {
143 if err := setUserStr(spec, spec.Process.User.Username); err != nil {
144 return err
145 }
146 }
147
148
149 spec.Linux.CgroupsPath = "/containers/" + id
150
151 if spec.Windows != nil {
152
153 if specHasGPUDevice(spec) {
154
155
156
157 ldconfigHook := hooks.NewOCIHook("/sbin/ldconfig", []string{getNvidiaDriversUsrLibPath()}, os.Environ())
158 if err := hooks.AddOCIHook(spec, hooks.CreateRuntime, ldconfigHook); err != nil {
159 return err
160 }
161 if err := addNvidiaDeviceHook(ctx, spec); err != nil {
162 return err
163 }
164 }
165
166 if err := addAssignedDevice(ctx, spec); err != nil {
167 return errors.Wrap(err, "failed to add assigned device(s) to the container spec")
168 }
169 }
170
171
172 spec.Windows = nil
173
174 return nil
175 }
176
View as plain text