podman

Форк
0
/
container_inspect_linux.go 
320 строк · 10.0 Кб
1
//go:build !remote
2

3
package libpod
4

5
import (
6
	"fmt"
7
	"sort"
8
	"strings"
9

10
	"github.com/containers/common/pkg/config"
11
	"github.com/containers/podman/v5/libpod/define"
12
	"github.com/containers/podman/v5/pkg/util"
13
	spec "github.com/opencontainers/runtime-spec/specs-go"
14
	"github.com/opencontainers/runtime-tools/generate"
15
	"github.com/opencontainers/runtime-tools/validate/capabilities"
16
	"github.com/sirupsen/logrus"
17
	"github.com/syndtr/gocapability/capability"
18
)
19

20
func (c *Container) platformInspectContainerHostConfig(ctrSpec *spec.Spec, hostConfig *define.InspectContainerHostConfig) error {
21
	// This is very expensive to initialize.
22
	// So we don't want to initialize it unless we absolutely have to - IE,
23
	// there are things that require a major:minor to path translation.
24
	var deviceNodes map[string]string
25

26
	if ctrSpec.Linux != nil {
27
		if ctrSpec.Linux.IntelRdt != nil {
28
			if ctrSpec.Linux.IntelRdt.ClosID != "" {
29
				// container is assigned to a ClosID
30
				hostConfig.IntelRdtClosID = ctrSpec.Linux.IntelRdt.ClosID
31
			}
32
		}
33
		// Resource limits
34
		if ctrSpec.Linux.Resources != nil {
35
			if ctrSpec.Linux.Resources.CPU != nil {
36
				if ctrSpec.Linux.Resources.CPU.Shares != nil {
37
					hostConfig.CpuShares = *ctrSpec.Linux.Resources.CPU.Shares
38
				}
39
				if ctrSpec.Linux.Resources.CPU.Period != nil {
40
					hostConfig.CpuPeriod = *ctrSpec.Linux.Resources.CPU.Period
41
				}
42
				if ctrSpec.Linux.Resources.CPU.Quota != nil {
43
					hostConfig.CpuQuota = *ctrSpec.Linux.Resources.CPU.Quota
44
				}
45
				if ctrSpec.Linux.Resources.CPU.RealtimePeriod != nil {
46
					hostConfig.CpuRealtimePeriod = *ctrSpec.Linux.Resources.CPU.RealtimePeriod
47
				}
48
				if ctrSpec.Linux.Resources.CPU.RealtimeRuntime != nil {
49
					hostConfig.CpuRealtimeRuntime = *ctrSpec.Linux.Resources.CPU.RealtimeRuntime
50
				}
51
				hostConfig.CpusetCpus = ctrSpec.Linux.Resources.CPU.Cpus
52
				hostConfig.CpusetMems = ctrSpec.Linux.Resources.CPU.Mems
53
			}
54
			if ctrSpec.Linux.Resources.Memory != nil {
55
				if ctrSpec.Linux.Resources.Memory.Limit != nil {
56
					hostConfig.Memory = *ctrSpec.Linux.Resources.Memory.Limit
57
				}
58
				if ctrSpec.Linux.Resources.Memory.Reservation != nil {
59
					hostConfig.MemoryReservation = *ctrSpec.Linux.Resources.Memory.Reservation
60
				}
61
				if ctrSpec.Linux.Resources.Memory.Swap != nil {
62
					hostConfig.MemorySwap = *ctrSpec.Linux.Resources.Memory.Swap
63
				}
64
				if ctrSpec.Linux.Resources.Memory.Swappiness != nil {
65
					hostConfig.MemorySwappiness = int64(*ctrSpec.Linux.Resources.Memory.Swappiness)
66
				} else {
67
					// Swappiness has a default of -1
68
					hostConfig.MemorySwappiness = -1
69
				}
70
				if ctrSpec.Linux.Resources.Memory.DisableOOMKiller != nil {
71
					hostConfig.OomKillDisable = *ctrSpec.Linux.Resources.Memory.DisableOOMKiller
72
				}
73
			}
74
			if ctrSpec.Linux.Resources.Pids != nil {
75
				hostConfig.PidsLimit = ctrSpec.Linux.Resources.Pids.Limit
76
			}
77
			hostConfig.CgroupConf = ctrSpec.Linux.Resources.Unified
78
			if ctrSpec.Linux.Resources.BlockIO != nil {
79
				if ctrSpec.Linux.Resources.BlockIO.Weight != nil {
80
					hostConfig.BlkioWeight = *ctrSpec.Linux.Resources.BlockIO.Weight
81
				}
82
				hostConfig.BlkioWeightDevice = []define.InspectBlkioWeightDevice{}
83
				for _, dev := range ctrSpec.Linux.Resources.BlockIO.WeightDevice {
84
					key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
85
					// TODO: how do we handle LeafWeight vs
86
					// Weight? For now, ignore anything
87
					// without Weight set.
88
					if dev.Weight == nil {
89
						logrus.Infof("Ignoring weight device %s as it lacks a weight", key)
90
						continue
91
					}
92
					if deviceNodes == nil {
93
						nodes, err := util.FindDeviceNodes()
94
						if err != nil {
95
							return err
96
						}
97
						deviceNodes = nodes
98
					}
99
					path, ok := deviceNodes[key]
100
					if !ok {
101
						logrus.Infof("Could not locate weight device %s in system devices", key)
102
						continue
103
					}
104
					weightDev := define.InspectBlkioWeightDevice{}
105
					weightDev.Path = path
106
					weightDev.Weight = *dev.Weight
107
					hostConfig.BlkioWeightDevice = append(hostConfig.BlkioWeightDevice, weightDev)
108
				}
109

110
				readBps, err := blkioDeviceThrottle(deviceNodes, ctrSpec.Linux.Resources.BlockIO.ThrottleReadBpsDevice)
111
				if err != nil {
112
					return err
113
				}
114
				hostConfig.BlkioDeviceReadBps = readBps
115

116
				writeBps, err := blkioDeviceThrottle(deviceNodes, ctrSpec.Linux.Resources.BlockIO.ThrottleWriteBpsDevice)
117
				if err != nil {
118
					return err
119
				}
120
				hostConfig.BlkioDeviceWriteBps = writeBps
121

122
				readIops, err := blkioDeviceThrottle(deviceNodes, ctrSpec.Linux.Resources.BlockIO.ThrottleReadIOPSDevice)
123
				if err != nil {
124
					return err
125
				}
126
				hostConfig.BlkioDeviceReadIOps = readIops
127

128
				writeIops, err := blkioDeviceThrottle(deviceNodes, ctrSpec.Linux.Resources.BlockIO.ThrottleWriteIOPSDevice)
129
				if err != nil {
130
					return err
131
				}
132
				hostConfig.BlkioDeviceWriteIOps = writeIops
133
			}
134
		}
135
	}
136

137
	// Cap add and cap drop.
138
	// We need a default set of capabilities to compare against.
139
	// The OCI generate package has one, and is commonly used, so we'll
140
	// use it.
141
	// Problem: there are 5 sets of capabilities.
142
	// Use the bounding set for this computation, it's the most encompassing
143
	// (but still not perfect).
144
	capAdd := []string{}
145
	capDrop := []string{}
146
	// No point in continuing if we got a spec without a Process block...
147
	if ctrSpec.Process != nil {
148
		// Max an O(1) lookup table for default bounding caps.
149
		boundingCaps := make(map[string]bool)
150
		if !hostConfig.Privileged {
151
			for _, cap := range c.runtime.config.Containers.DefaultCapabilities.Get() {
152
				boundingCaps[cap] = true
153
			}
154
		} else {
155
			g, err := generate.New("linux")
156
			if err != nil {
157
				return err
158
			}
159
			// If we are privileged, use all caps.
160
			for _, cap := range capability.List() {
161
				if g.HostSpecific && cap > capabilities.LastCap() {
162
					continue
163
				}
164
				boundingCaps[fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String()))] = true
165
			}
166
		}
167
		// Iterate through default caps.
168
		// If it's not in default bounding caps, it was added.
169
		// If it is, delete from the default set. Whatever remains after
170
		// we finish are the dropped caps.
171
		for _, cap := range ctrSpec.Process.Capabilities.Bounding {
172
			if _, ok := boundingCaps[cap]; ok {
173
				delete(boundingCaps, cap)
174
			} else {
175
				capAdd = append(capAdd, cap)
176
			}
177
		}
178
		for cap := range boundingCaps {
179
			capDrop = append(capDrop, cap)
180
		}
181
		// Sort CapDrop so it displays in consistent order (GH #9490)
182
		sort.Strings(capDrop)
183
	}
184
	hostConfig.CapAdd = capAdd
185
	hostConfig.CapDrop = capDrop
186
	switch {
187
	case c.config.IPCNsCtr != "":
188
		hostConfig.IpcMode = fmt.Sprintf("container:%s", c.config.IPCNsCtr)
189
	case ctrSpec.Linux != nil:
190
		// Locate the spec's IPC namespace.
191
		// If there is none, it's ipc=host.
192
		// If there is one and it has a path, it's "ns:".
193
		// If no path, it's default - the empty string.
194
		hostConfig.IpcMode = "host"
195
		for _, ns := range ctrSpec.Linux.Namespaces {
196
			if ns.Type == spec.IPCNamespace {
197
				if ns.Path != "" {
198
					hostConfig.IpcMode = fmt.Sprintf("ns:%s", ns.Path)
199
				} else {
200
					switch {
201
					case c.config.NoShm:
202
						hostConfig.IpcMode = "none"
203
					case c.config.NoShmShare:
204
						hostConfig.IpcMode = "private"
205
					default:
206
						hostConfig.IpcMode = "shareable"
207
					}
208
				}
209
				break
210
			}
211
		}
212
	case c.config.NoShm:
213
		hostConfig.IpcMode = "none"
214
	case c.config.NoShmShare:
215
		hostConfig.IpcMode = "private"
216
	}
217

218
	// Cgroup namespace mode
219
	cgroupMode := ""
220
	if c.config.CgroupNsCtr != "" {
221
		cgroupMode = fmt.Sprintf("container:%s", c.config.CgroupNsCtr)
222
	} else if ctrSpec.Linux != nil {
223
		// Locate the spec's cgroup namespace
224
		// If there is none, it's cgroup=host.
225
		// If there is one and it has a path, it's "ns:".
226
		// If there is no path, it's private.
227
		for _, ns := range ctrSpec.Linux.Namespaces {
228
			if ns.Type == spec.CgroupNamespace {
229
				if ns.Path != "" {
230
					cgroupMode = fmt.Sprintf("ns:%s", ns.Path)
231
				} else {
232
					cgroupMode = "private"
233
				}
234
			}
235
		}
236
		if cgroupMode == "" {
237
			cgroupMode = "host"
238
		}
239
	}
240
	hostConfig.CgroupMode = cgroupMode
241

242
	// Cgroup parent
243
	// Need to check if it's the default, and not print if so.
244
	defaultCgroupParent := ""
245
	switch c.CgroupManager() {
246
	case config.CgroupfsCgroupsManager:
247
		defaultCgroupParent = CgroupfsDefaultCgroupParent
248
	case config.SystemdCgroupsManager:
249
		defaultCgroupParent = SystemdDefaultCgroupParent
250
	}
251
	if c.config.CgroupParent != defaultCgroupParent {
252
		hostConfig.CgroupParent = c.config.CgroupParent
253
	}
254
	hostConfig.CgroupManager = c.CgroupManager()
255

256
	// PID namespace mode
257
	pidMode := ""
258
	if c.config.PIDNsCtr != "" {
259
		pidMode = fmt.Sprintf("container:%s", c.config.PIDNsCtr)
260
	} else if ctrSpec.Linux != nil {
261
		// Locate the spec's PID namespace.
262
		// If there is none, it's pid=host.
263
		// If there is one and it has a path, it's "ns:".
264
		// If there is no path, it's default - the empty string.
265
		for _, ns := range ctrSpec.Linux.Namespaces {
266
			if ns.Type == spec.PIDNamespace {
267
				if ns.Path != "" {
268
					pidMode = fmt.Sprintf("ns:%s", ns.Path)
269
				} else {
270
					pidMode = "private"
271
				}
272
				break
273
			}
274
		}
275
		if pidMode == "" {
276
			pidMode = "host"
277
		}
278
	}
279
	hostConfig.PidMode = pidMode
280

281
	// UTS namespace mode
282
	utsMode := c.NamespaceMode(spec.UTSNamespace, ctrSpec)
283

284
	hostConfig.UTSMode = utsMode
285

286
	// User namespace mode
287
	usernsMode := ""
288
	if c.config.UserNsCtr != "" {
289
		usernsMode = fmt.Sprintf("container:%s", c.config.UserNsCtr)
290
	} else if ctrSpec.Linux != nil {
291
		// Locate the spec's user namespace.
292
		// If there is none, it's default - the empty string.
293
		// If there is one, it's "private" if no path, or "ns:" if
294
		// there's a path.
295

296
		for _, ns := range ctrSpec.Linux.Namespaces {
297
			if ns.Type == spec.UserNamespace {
298
				if ns.Path != "" {
299
					usernsMode = fmt.Sprintf("ns:%s", ns.Path)
300
				} else {
301
					usernsMode = "private"
302
				}
303
			}
304
		}
305
	}
306
	hostConfig.UsernsMode = usernsMode
307
	if c.config.IDMappings.UIDMap != nil && c.config.IDMappings.GIDMap != nil {
308
		hostConfig.IDMappings = generateIDMappings(c.config.IDMappings)
309
	}
310
	// Devices
311
	// Do not include if privileged - assumed that all devices will be
312
	// included.
313
	var err error
314
	hostConfig.Devices, err = c.GetDevices(hostConfig.Privileged, *ctrSpec, deviceNodes)
315
	if err != nil {
316
		return err
317
	}
318

319
	return nil
320
}
321

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.