mirror of
https://github.com/containers/podman.git
synced 2025-05-17 23:26:08 +08:00
151 lines
5.4 KiB
Go
151 lines
5.4 KiB
Go
//go:build !remote
|
|
// +build !remote
|
|
|
|
package libpod
|
|
|
|
import (
|
|
"fmt"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/containers/common/pkg/cgroups"
|
|
"github.com/containers/common/pkg/config"
|
|
"github.com/containers/podman/v4/libpod/define"
|
|
"github.com/containers/podman/v4/pkg/rootless"
|
|
"github.com/containers/podman/v4/utils"
|
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (r *Runtime) platformMakePod(pod *Pod, resourceLimits *spec.LinuxResources) (string, error) {
|
|
cgroupParent := ""
|
|
// Check Cgroup parent sanity, and set it if it was not set
|
|
if r.config.Cgroups() != "disabled" {
|
|
switch r.config.Engine.CgroupManager {
|
|
case config.CgroupfsCgroupsManager:
|
|
canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(pod.config.CgroupParent)
|
|
if canUseCgroup {
|
|
// need to actually create parent here
|
|
if pod.config.CgroupParent == "" {
|
|
pod.config.CgroupParent = CgroupfsDefaultCgroupParent
|
|
} else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
|
|
return "", fmt.Errorf("systemd slice received as cgroup parent when using cgroupfs: %w", define.ErrInvalidArg)
|
|
}
|
|
// If we are set to use pod cgroups, set the cgroup parent that
|
|
// all containers in the pod will share
|
|
if pod.config.UsePodCgroup {
|
|
pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
|
|
cgroupParent = pod.state.CgroupPath
|
|
// cgroupfs + rootless = permission denied when creating the cgroup.
|
|
if !rootless.IsRootless() {
|
|
res, err := GetLimits(resourceLimits)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// Need to both create and update the cgroup
|
|
// rather than create a new path in c/common for pod cgroup creation
|
|
// just create as if it is a ctr and then update figures out that we need to
|
|
// populate the resource limits on the pod level
|
|
cgc, err := cgroups.New(pod.state.CgroupPath, &res)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
err = cgc.Update(&res)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case config.SystemdCgroupsManager:
|
|
if pod.config.CgroupParent == "" {
|
|
if rootless.IsRootless() {
|
|
pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent
|
|
} else {
|
|
pod.config.CgroupParent = SystemdDefaultCgroupParent
|
|
}
|
|
} else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
|
|
return "", fmt.Errorf("did not receive systemd slice as cgroup parent when using systemd to manage cgroups: %w", define.ErrInvalidArg)
|
|
}
|
|
// If we are set to use pod cgroups, set the cgroup parent that
|
|
// all containers in the pod will share
|
|
if pod.config.UsePodCgroup {
|
|
cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()), resourceLimits)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to create pod cgroup for pod %s: %w", pod.ID(), err)
|
|
}
|
|
pod.state.CgroupPath = cgroupPath
|
|
cgroupParent = pod.state.CgroupPath
|
|
}
|
|
default:
|
|
return "", fmt.Errorf("unsupported Cgroup manager: %s - cannot validate cgroup parent: %w", r.config.Engine.CgroupManager, define.ErrInvalidArg)
|
|
}
|
|
}
|
|
|
|
if pod.config.UsePodCgroup {
|
|
logrus.Debugf("Got pod cgroup as %s", pod.state.CgroupPath)
|
|
}
|
|
|
|
return cgroupParent, nil
|
|
}
|
|
|
|
func (p *Pod) removePodCgroup() error {
|
|
// Remove pod cgroup, if present
|
|
if p.state.CgroupPath == "" {
|
|
return nil
|
|
}
|
|
logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath)
|
|
|
|
cgroup, err := utils.GetOwnCgroup()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// if we are trying to delete a cgroup that is our ancestor, we need to move the
|
|
// current process out of it before the cgroup is destroyed.
|
|
if isSubDir(cgroup, string(filepath.Separator)+p.state.CgroupPath) {
|
|
parent := path.Dir(p.state.CgroupPath)
|
|
if err := utils.MoveUnderCgroup(parent, "cleanup", nil); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
switch p.runtime.config.Engine.CgroupManager {
|
|
case config.SystemdCgroupsManager:
|
|
if err := deleteSystemdCgroup(p.state.CgroupPath, p.ResourceLim()); err != nil {
|
|
return fmt.Errorf("removing pod %s cgroup: %w", p.ID(), err)
|
|
}
|
|
case config.CgroupfsCgroupsManager:
|
|
// Delete the cgroupfs cgroup
|
|
// Make sure the conmon cgroup is deleted first
|
|
// Since the pod is almost gone, don't bother failing
|
|
// hard - instead, just log errors.
|
|
conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon")
|
|
conmonCgroup, err := cgroups.Load(conmonCgroupPath)
|
|
if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless {
|
|
return fmt.Errorf("retrieving pod %s conmon cgroup: %w", p.ID(), err)
|
|
}
|
|
if err == nil {
|
|
if err = conmonCgroup.Delete(); err != nil {
|
|
return fmt.Errorf("removing pod %s conmon cgroup: %w", p.ID(), err)
|
|
}
|
|
}
|
|
cgroup, err := cgroups.Load(p.state.CgroupPath)
|
|
if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless {
|
|
return fmt.Errorf("retrieving pod %s cgroup: %w", p.ID(), err)
|
|
}
|
|
if err == nil {
|
|
if err := cgroup.Delete(); err != nil {
|
|
return fmt.Errorf("removing pod %s cgroup: %w", p.ID(), err)
|
|
}
|
|
}
|
|
default:
|
|
// This should be caught much earlier, but let's still
|
|
// keep going so we make sure to evict the pod before
|
|
// ending up with an inconsistent state.
|
|
return fmt.Errorf("unrecognized cgroup manager %s when removing pod %s cgroups: %w", p.runtime.config.Engine.CgroupManager, p.ID(), define.ErrInternal)
|
|
}
|
|
return nil
|
|
}
|