11
"github.com/containers/common/pkg/cgroups"
12
"github.com/containers/common/pkg/config"
13
"github.com/containers/podman/v5/libpod/define"
14
"github.com/containers/podman/v5/pkg/rootless"
15
spec "github.com/opencontainers/runtime-spec/specs-go"
16
"github.com/sirupsen/logrus"
19
func (r *Runtime) platformMakePod(pod *Pod, resourceLimits *spec.LinuxResources) (string, error) {
21
// Check Cgroup parent sanity, and set it if it was not set
22
if r.config.Cgroups() != "disabled" {
23
switch r.config.Engine.CgroupManager {
24
case config.CgroupfsCgroupsManager:
25
canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(pod.config.CgroupParent)
27
// need to actually create parent here
28
if pod.config.CgroupParent == "" {
29
pod.config.CgroupParent = CgroupfsDefaultCgroupParent
30
} else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
31
return "", fmt.Errorf("systemd slice received as cgroup parent when using cgroupfs: %w", define.ErrInvalidArg)
33
// If we are set to use pod cgroups, set the cgroup parent that
34
// all containers in the pod will share
35
if pod.config.UsePodCgroup {
36
pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
37
cgroupParent = pod.state.CgroupPath
38
// cgroupfs + rootless = permission denied when creating the cgroup.
39
if !rootless.IsRootless() {
40
res, err := GetLimits(resourceLimits)
44
res.SkipDevices = true
45
// Need to both create and update the cgroup
46
// rather than create a new path in c/common for pod cgroup creation
47
// just create as if it is a ctr and then update figures out that we need to
48
// populate the resource limits on the pod level
49
cgc, err := cgroups.New(pod.state.CgroupPath, &res)
53
err = cgc.Update(&res)
60
case config.SystemdCgroupsManager:
61
if pod.config.CgroupParent == "" {
62
if rootless.IsRootless() {
63
pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent
65
pod.config.CgroupParent = SystemdDefaultCgroupParent
67
} else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
68
return "", fmt.Errorf("did not receive systemd slice as cgroup parent when using systemd to manage cgroups: %w", define.ErrInvalidArg)
70
// If we are set to use pod cgroups, set the cgroup parent that
71
// all containers in the pod will share
72
if pod.config.UsePodCgroup {
73
cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()), resourceLimits)
75
return "", fmt.Errorf("unable to create pod cgroup for pod %s: %w", pod.ID(), err)
77
pod.state.CgroupPath = cgroupPath
78
cgroupParent = pod.state.CgroupPath
81
return "", fmt.Errorf("unsupported Cgroup manager: %s - cannot validate cgroup parent: %w", r.config.Engine.CgroupManager, define.ErrInvalidArg)
85
if pod.config.UsePodCgroup {
86
logrus.Debugf("Got pod cgroup as %s", pod.state.CgroupPath)
89
return cgroupParent, nil
92
func (p *Pod) removePodCgroup() error {
93
// Remove pod cgroup, if present
94
if p.state.CgroupPath == "" {
97
logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath)
99
cgroup, err := cgroups.GetOwnCgroup()
104
// if we are trying to delete a cgroup that is our ancestor, we need to move the
105
// current process out of it before the cgroup is destroyed.
106
if isSubDir(cgroup, string(filepath.Separator)+p.state.CgroupPath) {
107
parent := path.Dir(p.state.CgroupPath)
108
if err := cgroups.MoveUnderCgroup(parent, "cleanup", nil); err != nil {
113
switch p.runtime.config.Engine.CgroupManager {
114
case config.SystemdCgroupsManager:
115
if err := deleteSystemdCgroup(p.state.CgroupPath, p.ResourceLim()); err != nil {
116
return fmt.Errorf("removing pod %s cgroup: %w", p.ID(), err)
118
case config.CgroupfsCgroupsManager:
119
// Delete the cgroupfs cgroup
120
// Make sure the conmon cgroup is deleted first
121
// Since the pod is almost gone, don't bother failing
122
// hard - instead, just log errors.
123
conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon")
124
conmonCgroup, err := cgroups.Load(conmonCgroupPath)
125
if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless {
126
return fmt.Errorf("retrieving pod %s conmon cgroup: %w", p.ID(), err)
129
if err = conmonCgroup.Delete(); err != nil {
130
return fmt.Errorf("removing pod %s conmon cgroup: %w", p.ID(), err)
133
cgroup, err := cgroups.Load(p.state.CgroupPath)
134
if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless {
135
return fmt.Errorf("retrieving pod %s cgroup: %w", p.ID(), err)
138
if err := cgroup.Delete(); err != nil {
139
return fmt.Errorf("removing pod %s cgroup: %w", p.ID(), err)
143
// This should be caught much earlier, but let's still
144
// keep going so we make sure to evict the pod before
145
// ending up with an inconsistent state.
146
return fmt.Errorf("unrecognized cgroup manager %s when removing pod %s cgroups: %w", p.runtime.config.Engine.CgroupManager, p.ID(), define.ErrInternal)