mirror of
				https://github.com/containers/podman.git
				synced 2025-11-04 17:07:20 +08:00 
			
		
		
		
	Moving from Go module v4 to v5 prepares us for public releases. Move done using gomove [1] as with the v3 and v4 moves. [1] https://github.com/KSubedi/gomove Signed-off-by: Matt Heon <mheon@redhat.com>
		
			
				
	
	
		
			150 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//go: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/v5/libpod/define"
 | 
						|
	"github.com/containers/podman/v5/pkg/rootless"
 | 
						|
	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
 | 
						|
						}
 | 
						|
						res.SkipDevices = true
 | 
						|
						// 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 := cgroups.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 := cgroups.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
 | 
						|
}
 |