1
2
3 package oci
4
5 import (
6 "context"
7 "errors"
8 "strconv"
9
10 runhcsopts "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options"
11 "github.com/Microsoft/hcsshim/internal/log"
12 "github.com/Microsoft/hcsshim/internal/uvm"
13 "github.com/Microsoft/hcsshim/pkg/annotations"
14 "github.com/opencontainers/runtime-spec/specs-go"
15 "github.com/sirupsen/logrus"
16 )
17
18
19
20
21
22
23 func ParseAnnotationsCPUCount(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
24 if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
25 return int32(m)
26 }
27 if s.Windows != nil &&
28 s.Windows.Resources != nil &&
29 s.Windows.Resources.CPU != nil &&
30 s.Windows.Resources.CPU.Count != nil &&
31 *s.Windows.Resources.CPU.Count > 0 {
32 return int32(*s.Windows.Resources.CPU.Count)
33 }
34 return def
35 }
36
37
38
39
40 func ParseAnnotationsCPULimit(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
41 if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
42 return int32(m)
43 }
44 if s.Windows != nil &&
45 s.Windows.Resources != nil &&
46 s.Windows.Resources.CPU != nil &&
47 s.Windows.Resources.CPU.Maximum != nil &&
48 *s.Windows.Resources.CPU.Maximum > 0 {
49 return int32(*s.Windows.Resources.CPU.Maximum)
50 }
51 return def
52 }
53
54
55
56
57 func ParseAnnotationsCPUWeight(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
58 if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
59 return int32(m)
60 }
61 if s.Windows != nil &&
62 s.Windows.Resources != nil &&
63 s.Windows.Resources.CPU != nil &&
64 s.Windows.Resources.CPU.Shares != nil &&
65 *s.Windows.Resources.CPU.Shares > 0 {
66 return int32(*s.Windows.Resources.CPU.Shares)
67 }
68 return def
69 }
70
71
72
73
74 func ParseAnnotationsStorageIops(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
75 if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
76 return int32(m)
77 }
78 if s.Windows != nil &&
79 s.Windows.Resources != nil &&
80 s.Windows.Resources.Storage != nil &&
81 s.Windows.Resources.Storage.Iops != nil &&
82 *s.Windows.Resources.Storage.Iops > 0 {
83 return int32(*s.Windows.Resources.Storage.Iops)
84 }
85 return def
86 }
87
88
89
90
91 func ParseAnnotationsStorageBps(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
92 if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
93 return int32(m)
94 }
95 if s.Windows != nil &&
96 s.Windows.Resources != nil &&
97 s.Windows.Resources.Storage != nil &&
98 s.Windows.Resources.Storage.Bps != nil &&
99 *s.Windows.Resources.Storage.Bps > 0 {
100 return int32(*s.Windows.Resources.Storage.Bps)
101 }
102 return def
103 }
104
105
106
107
108
109
110 func ParseAnnotationsMemory(ctx context.Context, s *specs.Spec, annotation string, def uint64) uint64 {
111 if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
112 return m
113 }
114 if s.Windows != nil &&
115 s.Windows.Resources != nil &&
116 s.Windows.Resources.Memory != nil &&
117 s.Windows.Resources.Memory.Limit != nil &&
118 *s.Windows.Resources.Memory.Limit > 0 {
119 return (*s.Windows.Resources.Memory.Limit / 1024 / 1024)
120 }
121 return def
122 }
123
124
125
126 func parseAnnotationsPreferredRootFSType(ctx context.Context, a map[string]string, key string, def uvm.PreferredRootFSType) uvm.PreferredRootFSType {
127 if v, ok := a[key]; ok {
128 switch v {
129 case "initrd":
130 return uvm.PreferredRootFSTypeInitRd
131 case "vhd":
132 return uvm.PreferredRootFSTypeVHD
133 default:
134 log.G(ctx).WithFields(logrus.Fields{
135 "annotation": key,
136 "value": v,
137 }).Warn("annotation value must be 'initrd' or 'vhd'")
138 }
139 }
140 return def
141 }
142
143
144
145 func handleAnnotationKernelDirectBoot(ctx context.Context, a map[string]string, lopts *uvm.OptionsLCOW) {
146 lopts.KernelDirect = ParseAnnotationsBool(ctx, a, annotations.KernelDirectBoot, lopts.KernelDirect)
147 if !lopts.KernelDirect {
148 lopts.KernelFile = uvm.KernelFile
149 }
150 }
151
152
153
154 func handleAnnotationPreferredRootFSType(ctx context.Context, a map[string]string, lopts *uvm.OptionsLCOW) {
155 lopts.PreferredRootFSType = parseAnnotationsPreferredRootFSType(ctx, a, annotations.PreferredRootFSType, lopts.PreferredRootFSType)
156 switch lopts.PreferredRootFSType {
157 case uvm.PreferredRootFSTypeInitRd:
158 lopts.RootFSFile = uvm.InitrdFile
159 case uvm.PreferredRootFSTypeVHD:
160 lopts.RootFSFile = uvm.VhdFile
161 }
162 }
163
164
165
166 func handleAnnotationFullyPhysicallyBacked(ctx context.Context, a map[string]string, opts interface{}) {
167 switch options := opts.(type) {
168 case *uvm.OptionsLCOW:
169 options.FullyPhysicallyBacked = ParseAnnotationsBool(ctx, a, annotations.FullyPhysicallyBacked, options.FullyPhysicallyBacked)
170 if options.FullyPhysicallyBacked {
171 options.AllowOvercommit = false
172 options.PreferredRootFSType = uvm.PreferredRootFSTypeInitRd
173 options.RootFSFile = uvm.InitrdFile
174 options.VPMemDeviceCount = 0
175 }
176 case *uvm.OptionsWCOW:
177 options.FullyPhysicallyBacked = ParseAnnotationsBool(ctx, a, annotations.FullyPhysicallyBacked, options.FullyPhysicallyBacked)
178 if options.FullyPhysicallyBacked {
179 options.AllowOvercommit = false
180 }
181 }
182 }
183
184
185
186 func handleSecurityPolicy(ctx context.Context, a map[string]string, lopts *uvm.OptionsLCOW) {
187 lopts.SecurityPolicy = parseAnnotationsString(a, annotations.SecurityPolicy, lopts.SecurityPolicy)
188
189
190 noSecurityHardware := ParseAnnotationsBool(ctx, a, annotations.NoSecurityHardware, false)
191
192
193
194
195
196 if len(lopts.SecurityPolicy) > 0 && !noSecurityHardware {
197
198 lopts.VPMemDeviceCount = 0
199
200 lopts.GuestStateFile = uvm.GuestStateFile
201 lopts.KernelBootOptions = ""
202 lopts.PreferredRootFSType = uvm.PreferredRootFSTypeNA
203 lopts.AllowOvercommit = false
204 lopts.SecurityPolicyEnabled = true
205 }
206
207 if len(lopts.SecurityPolicy) > 0 {
208
209 lopts.EnableScratchEncryption = ParseAnnotationsBool(ctx, a, annotations.EncryptedScratchDisk, true)
210 }
211 }
212
213
214 func specToUVMCreateOptionsCommon(ctx context.Context, opts *uvm.Options, s *specs.Spec) {
215 opts.MemorySizeInMB = ParseAnnotationsMemory(ctx, s, annotations.MemorySizeInMB, opts.MemorySizeInMB)
216 opts.LowMMIOGapInMB = parseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryLowMMIOGapInMB, opts.LowMMIOGapInMB)
217 opts.HighMMIOBaseInMB = parseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryHighMMIOBaseInMB, opts.HighMMIOBaseInMB)
218 opts.HighMMIOGapInMB = parseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryHighMMIOGapInMB, opts.HighMMIOGapInMB)
219 opts.AllowOvercommit = ParseAnnotationsBool(ctx, s.Annotations, annotations.AllowOvercommit, opts.AllowOvercommit)
220 opts.EnableDeferredCommit = ParseAnnotationsBool(ctx, s.Annotations, annotations.EnableDeferredCommit, opts.EnableDeferredCommit)
221 opts.ProcessorCount = ParseAnnotationsCPUCount(ctx, s, annotations.ProcessorCount, opts.ProcessorCount)
222 opts.ProcessorLimit = ParseAnnotationsCPULimit(ctx, s, annotations.ProcessorLimit, opts.ProcessorLimit)
223 opts.ProcessorWeight = ParseAnnotationsCPUWeight(ctx, s, annotations.ProcessorWeight, opts.ProcessorWeight)
224 opts.StorageQoSBandwidthMaximum = ParseAnnotationsStorageBps(ctx, s, annotations.StorageQoSBandwidthMaximum, opts.StorageQoSBandwidthMaximum)
225 opts.StorageQoSIopsMaximum = ParseAnnotationsStorageIops(ctx, s, annotations.StorageQoSIopsMaximum, opts.StorageQoSIopsMaximum)
226 opts.CPUGroupID = parseAnnotationsString(s.Annotations, annotations.CPUGroupID, opts.CPUGroupID)
227 opts.NetworkConfigProxy = parseAnnotationsString(s.Annotations, annotations.NetworkConfigProxy, opts.NetworkConfigProxy)
228 opts.ProcessDumpLocation = parseAnnotationsString(s.Annotations, annotations.ContainerProcessDumpLocation, opts.ProcessDumpLocation)
229 opts.NoWritableFileShares = ParseAnnotationsBool(ctx, s.Annotations, annotations.DisableWritableFileShares, opts.NoWritableFileShares)
230 opts.DumpDirectoryPath = parseAnnotationsString(s.Annotations, annotations.DumpDirectoryPath, opts.DumpDirectoryPath)
231 }
232
233
234
235 func SpecToUVMCreateOpts(ctx context.Context, s *specs.Spec, id, owner string) (interface{}, error) {
236 if !IsIsolated(s) {
237 return nil, errors.New("cannot create UVM opts for non-isolated spec")
238 }
239 if IsLCOW(s) {
240 lopts := uvm.NewDefaultOptionsLCOW(id, owner)
241 specToUVMCreateOptionsCommon(ctx, lopts.Options, s)
242
243
251
252 lopts.EnableColdDiscardHint = ParseAnnotationsBool(ctx, s.Annotations, annotations.EnableColdDiscardHint, lopts.EnableColdDiscardHint)
253 lopts.VPMemDeviceCount = parseAnnotationsUint32(ctx, s.Annotations, annotations.VPMemCount, lopts.VPMemDeviceCount)
254 lopts.VPMemSizeBytes = parseAnnotationsUint64(ctx, s.Annotations, annotations.VPMemSize, lopts.VPMemSizeBytes)
255 lopts.VPMemNoMultiMapping = ParseAnnotationsBool(ctx, s.Annotations, annotations.VPMemNoMultiMapping, lopts.VPMemNoMultiMapping)
256 lopts.VPCIEnabled = ParseAnnotationsBool(ctx, s.Annotations, annotations.VPCIEnabled, lopts.VPCIEnabled)
257 lopts.BootFilesPath = parseAnnotationsString(s.Annotations, annotations.BootFilesRootPath, lopts.BootFilesPath)
258 lopts.EnableScratchEncryption = ParseAnnotationsBool(ctx, s.Annotations, annotations.EncryptedScratchDisk, lopts.EnableScratchEncryption)
259 lopts.SecurityPolicy = parseAnnotationsString(s.Annotations, annotations.SecurityPolicy, lopts.SecurityPolicy)
260 lopts.SecurityPolicyEnforcer = parseAnnotationsString(s.Annotations, annotations.SecurityPolicyEnforcer, lopts.SecurityPolicyEnforcer)
261 lopts.UVMReferenceInfoFile = parseAnnotationsString(s.Annotations, annotations.UVMReferenceInfoFile, lopts.UVMReferenceInfoFile)
262 lopts.KernelBootOptions = parseAnnotationsString(s.Annotations, annotations.KernelBootOptions, lopts.KernelBootOptions)
263 lopts.DisableTimeSyncService = ParseAnnotationsBool(ctx, s.Annotations, annotations.DisableLCOWTimeSyncService, lopts.DisableTimeSyncService)
264 handleAnnotationPreferredRootFSType(ctx, s.Annotations, lopts)
265 handleAnnotationKernelDirectBoot(ctx, s.Annotations, lopts)
266
267
268
269 handleAnnotationFullyPhysicallyBacked(ctx, s.Annotations, lopts)
270
271
272
273 handleSecurityPolicy(ctx, s.Annotations, lopts)
274
275
276 lopts.GuestStateFile = parseAnnotationsString(s.Annotations, annotations.GuestStateFile, lopts.GuestStateFile)
277 return lopts, nil
278 } else if IsWCOW(s) {
279 wopts := uvm.NewDefaultOptionsWCOW(id, owner)
280 specToUVMCreateOptionsCommon(ctx, wopts.Options, s)
281
282 wopts.DisableCompartmentNamespace = ParseAnnotationsBool(ctx, s.Annotations, annotations.DisableCompartmentNamespace, wopts.DisableCompartmentNamespace)
283 wopts.NoDirectMap = ParseAnnotationsBool(ctx, s.Annotations, annotations.VSMBNoDirectMap, wopts.NoDirectMap)
284 wopts.NoInheritHostTimezone = ParseAnnotationsBool(ctx, s.Annotations, annotations.NoInheritHostTimezone, wopts.NoInheritHostTimezone)
285 handleAnnotationFullyPhysicallyBacked(ctx, s.Annotations, wopts)
286 return wopts, nil
287 }
288 return nil, errors.New("cannot create UVM opts spec is not LCOW or WCOW")
289 }
290
291
292
293 func UpdateSpecFromOptions(s specs.Spec, opts *runhcsopts.Options) specs.Spec {
294 if opts == nil {
295 return s
296 }
297
298 if _, ok := s.Annotations[annotations.BootFilesRootPath]; !ok && opts.BootFilesRootPath != "" {
299 s.Annotations[annotations.BootFilesRootPath] = opts.BootFilesRootPath
300 }
301
302 if _, ok := s.Annotations[annotations.ProcessorCount]; !ok && opts.VmProcessorCount != 0 {
303 s.Annotations[annotations.ProcessorCount] = strconv.FormatInt(int64(opts.VmProcessorCount), 10)
304 }
305
306 if _, ok := s.Annotations[annotations.MemorySizeInMB]; !ok && opts.VmMemorySizeInMb != 0 {
307 s.Annotations[annotations.MemorySizeInMB] = strconv.FormatInt(int64(opts.VmMemorySizeInMb), 10)
308 }
309
310 if _, ok := s.Annotations[annotations.GPUVHDPath]; !ok && opts.GPUVHDPath != "" {
311 s.Annotations[annotations.GPUVHDPath] = opts.GPUVHDPath
312 }
313
314 if _, ok := s.Annotations[annotations.NetworkConfigProxy]; !ok && opts.NCProxyAddr != "" {
315 s.Annotations[annotations.NetworkConfigProxy] = opts.NCProxyAddr
316 }
317
318 for key, value := range opts.DefaultContainerAnnotations {
319
320 if _, ok := s.Annotations[key]; !ok {
321 s.Annotations[key] = value
322 }
323 }
324
325 return s
326 }
327
View as plain text