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"
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
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
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
39
if ctrSpec.Linux.Resources.CPU.Period != nil {
40
hostConfig.CpuPeriod = *ctrSpec.Linux.Resources.CPU.Period
42
if ctrSpec.Linux.Resources.CPU.Quota != nil {
43
hostConfig.CpuQuota = *ctrSpec.Linux.Resources.CPU.Quota
45
if ctrSpec.Linux.Resources.CPU.RealtimePeriod != nil {
46
hostConfig.CpuRealtimePeriod = *ctrSpec.Linux.Resources.CPU.RealtimePeriod
48
if ctrSpec.Linux.Resources.CPU.RealtimeRuntime != nil {
49
hostConfig.CpuRealtimeRuntime = *ctrSpec.Linux.Resources.CPU.RealtimeRuntime
51
hostConfig.CpusetCpus = ctrSpec.Linux.Resources.CPU.Cpus
52
hostConfig.CpusetMems = ctrSpec.Linux.Resources.CPU.Mems
54
if ctrSpec.Linux.Resources.Memory != nil {
55
if ctrSpec.Linux.Resources.Memory.Limit != nil {
56
hostConfig.Memory = *ctrSpec.Linux.Resources.Memory.Limit
58
if ctrSpec.Linux.Resources.Memory.Reservation != nil {
59
hostConfig.MemoryReservation = *ctrSpec.Linux.Resources.Memory.Reservation
61
if ctrSpec.Linux.Resources.Memory.Swap != nil {
62
hostConfig.MemorySwap = *ctrSpec.Linux.Resources.Memory.Swap
64
if ctrSpec.Linux.Resources.Memory.Swappiness != nil {
65
hostConfig.MemorySwappiness = int64(*ctrSpec.Linux.Resources.Memory.Swappiness)
67
// Swappiness has a default of -1
68
hostConfig.MemorySwappiness = -1
70
if ctrSpec.Linux.Resources.Memory.DisableOOMKiller != nil {
71
hostConfig.OomKillDisable = *ctrSpec.Linux.Resources.Memory.DisableOOMKiller
74
if ctrSpec.Linux.Resources.Pids != nil {
75
hostConfig.PidsLimit = ctrSpec.Linux.Resources.Pids.Limit
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
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)
92
if deviceNodes == nil {
93
nodes, err := util.FindDeviceNodes()
99
path, ok := deviceNodes[key]
101
logrus.Infof("Could not locate weight device %s in system devices", key)
104
weightDev := define.InspectBlkioWeightDevice{}
105
weightDev.Path = path
106
weightDev.Weight = *dev.Weight
107
hostConfig.BlkioWeightDevice = append(hostConfig.BlkioWeightDevice, weightDev)
110
readBps, err := blkioDeviceThrottle(deviceNodes, ctrSpec.Linux.Resources.BlockIO.ThrottleReadBpsDevice)
114
hostConfig.BlkioDeviceReadBps = readBps
116
writeBps, err := blkioDeviceThrottle(deviceNodes, ctrSpec.Linux.Resources.BlockIO.ThrottleWriteBpsDevice)
120
hostConfig.BlkioDeviceWriteBps = writeBps
122
readIops, err := blkioDeviceThrottle(deviceNodes, ctrSpec.Linux.Resources.BlockIO.ThrottleReadIOPSDevice)
126
hostConfig.BlkioDeviceReadIOps = readIops
128
writeIops, err := blkioDeviceThrottle(deviceNodes, ctrSpec.Linux.Resources.BlockIO.ThrottleWriteIOPSDevice)
132
hostConfig.BlkioDeviceWriteIOps = writeIops
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
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).
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
155
g, err := generate.New("linux")
159
// If we are privileged, use all caps.
160
for _, cap := range capability.List() {
161
if g.HostSpecific && cap > capabilities.LastCap() {
164
boundingCaps[fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String()))] = true
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)
175
capAdd = append(capAdd, cap)
178
for cap := range boundingCaps {
179
capDrop = append(capDrop, cap)
181
// Sort CapDrop so it displays in consistent order (GH #9490)
182
sort.Strings(capDrop)
184
hostConfig.CapAdd = capAdd
185
hostConfig.CapDrop = capDrop
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 {
198
hostConfig.IpcMode = fmt.Sprintf("ns:%s", ns.Path)
202
hostConfig.IpcMode = "none"
203
case c.config.NoShmShare:
204
hostConfig.IpcMode = "private"
206
hostConfig.IpcMode = "shareable"
213
hostConfig.IpcMode = "none"
214
case c.config.NoShmShare:
215
hostConfig.IpcMode = "private"
218
// Cgroup namespace mode
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 {
230
cgroupMode = fmt.Sprintf("ns:%s", ns.Path)
232
cgroupMode = "private"
236
if cgroupMode == "" {
240
hostConfig.CgroupMode = cgroupMode
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
251
if c.config.CgroupParent != defaultCgroupParent {
252
hostConfig.CgroupParent = c.config.CgroupParent
254
hostConfig.CgroupManager = c.CgroupManager()
256
// PID namespace mode
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 {
268
pidMode = fmt.Sprintf("ns:%s", ns.Path)
279
hostConfig.PidMode = pidMode
281
// UTS namespace mode
282
utsMode := c.NamespaceMode(spec.UTSNamespace, ctrSpec)
284
hostConfig.UTSMode = utsMode
286
// User namespace mode
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
296
for _, ns := range ctrSpec.Linux.Namespaces {
297
if ns.Type == spec.UserNamespace {
299
usernsMode = fmt.Sprintf("ns:%s", ns.Path)
301
usernsMode = "private"
306
hostConfig.UsernsMode = usernsMode
307
if c.config.IDMappings.UIDMap != nil && c.config.IDMappings.GIDMap != nil {
308
hostConfig.IDMappings = generateIDMappings(c.config.IDMappings)
311
// Do not include if privileged - assumed that all devices will be
314
hostConfig.Devices, err = c.GetDevices(hostConfig.Privileged, *ctrSpec, deviceNodes)