mirror of
				https://github.com/containers/podman.git
				synced 2025-10-31 10:00:01 +08:00 
			
		
		
		
	 667311c7d5
			
		
	
	667311c7d5
	
	
	
		
			
			Conmon writes the exit file and oom file (if container was oom killed) to the persist directory. This directory is retained across reboots as well. Update podman to create a persist-dir/ctr-id for the exit and oom files for each container to be written to. The oom state of container is set after reading the files from the persist-dir/ctr-id directory. The exit code still continues to read the exit file from the exits directory. Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
		
			
				
	
	
		
			249 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| //go:build !remote
 | |
| 
 | |
| package libpod
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"path/filepath"
 | |
| 	"sync"
 | |
| 
 | |
| 	"github.com/containers/common/pkg/resize"
 | |
| 	"github.com/containers/podman/v5/libpod/define"
 | |
| 	spec "github.com/opencontainers/runtime-spec/specs-go"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	// Only create each missing runtime once.
 | |
| 	// Creation makes error messages we don't want to duplicate.
 | |
| 	missingRuntimes map[string]*MissingRuntime
 | |
| 	// We need a lock for this
 | |
| 	missingRuntimesLock sync.Mutex
 | |
| )
 | |
| 
 | |
| // MissingRuntime is used when the OCI runtime requested by the container is
 | |
| // missing (not installed or not in the configuration file).
 | |
| type MissingRuntime struct {
 | |
| 	// Name is the name of the missing runtime. Will be used in errors.
 | |
| 	name string
 | |
| 	// exitsDir is the directory for exit files.
 | |
| 	exitsDir string
 | |
| 	// persistDir is the directory for exit and oom files.
 | |
| 	persistDir string
 | |
| }
 | |
| 
 | |
| // Get a new MissingRuntime for the given name.
 | |
| // Requires a libpod Runtime so we can make a sane path for the exits dir.
 | |
| func getMissingRuntime(name string, r *Runtime) OCIRuntime {
 | |
| 	missingRuntimesLock.Lock()
 | |
| 	defer missingRuntimesLock.Unlock()
 | |
| 
 | |
| 	if missingRuntimes == nil {
 | |
| 		missingRuntimes = make(map[string]*MissingRuntime)
 | |
| 	}
 | |
| 
 | |
| 	runtime, ok := missingRuntimes[name]
 | |
| 	if ok {
 | |
| 		return runtime
 | |
| 	}
 | |
| 
 | |
| 	// Once for each missing runtime, we want to error.
 | |
| 	logrus.Errorf("OCI Runtime %s is in use by a container, but is not available (not in configuration file or not installed)", name)
 | |
| 
 | |
| 	newRuntime := new(MissingRuntime)
 | |
| 	newRuntime.name = name
 | |
| 	newRuntime.exitsDir = filepath.Join(r.config.Engine.TmpDir, "exits")
 | |
| 	newRuntime.persistDir = filepath.Join(r.config.Engine.TmpDir, "persist")
 | |
| 
 | |
| 	missingRuntimes[name] = newRuntime
 | |
| 
 | |
| 	return newRuntime
 | |
| }
 | |
| 
 | |
| // Name is the name of the missing runtime
 | |
| func (r *MissingRuntime) Name() string {
 | |
| 	return fmt.Sprintf("%s (missing/not available)", r.name)
 | |
| }
 | |
| 
 | |
| // Path is not available as the runtime is missing
 | |
| func (r *MissingRuntime) Path() string {
 | |
| 	return "(missing/not available)"
 | |
| }
 | |
| 
 | |
| // CreateContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) (int64, error) {
 | |
| 	return 0, r.printError()
 | |
| }
 | |
| 
 | |
| // UpdateContainerStatus is not available as the runtime is missing
 | |
| func (r *MissingRuntime) UpdateContainerStatus(ctr *Container) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // StartContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) StartContainer(ctr *Container) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // UpdateContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) UpdateContainer(ctr *Container, resources *spec.LinuxResources) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // KillContainer is not available as the runtime is missing
 | |
| // TODO: We could attempt to unix.Kill() the PID as recorded in the state if we
 | |
| // really want to smooth things out? Won't be perfect, but if the container has
 | |
| // a PID namespace it could be enough?
 | |
| func (r *MissingRuntime) KillContainer(ctr *Container, signal uint, all bool) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // StopContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) StopContainer(ctr *Container, timeout uint, all bool) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // DeleteContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) DeleteContainer(ctr *Container) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // PauseContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) PauseContainer(ctr *Container) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // UnpauseContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) UnpauseContainer(ctr *Container) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // Attach is not available as the runtime is missing
 | |
| func (r *MissingRuntime) Attach(ctr *Container, params *AttachOptions) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // HTTPAttach is not available as the runtime is missing
 | |
| func (r *MissingRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, detachKeys *string, cancel <-chan bool, hijackDone chan<- bool, streamAttach, streamLogs bool) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // AttachResize is not available as the runtime is missing
 | |
| func (r *MissingRuntime) AttachResize(ctr *Container, newSize resize.TerminalSize) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // ExecContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *resize.TerminalSize) (int, chan error, error) {
 | |
| 	return -1, nil, r.printError()
 | |
| }
 | |
| 
 | |
| // ExecContainerHTTP is not available as the runtime is missing
 | |
| func (r *MissingRuntime) ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, req *http.Request, w http.ResponseWriter,
 | |
| 	streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *resize.TerminalSize) (int, chan error, error) {
 | |
| 	return -1, nil, r.printError()
 | |
| }
 | |
| 
 | |
| // ExecContainerDetached is not available as the runtime is missing
 | |
| func (r *MissingRuntime) ExecContainerDetached(ctr *Container, sessionID string, options *ExecOptions, stdin bool) (int, error) {
 | |
| 	return -1, r.printError()
 | |
| }
 | |
| 
 | |
| // ExecAttachResize is not available as the runtime is missing.
 | |
| func (r *MissingRuntime) ExecAttachResize(ctr *Container, sessionID string, newSize resize.TerminalSize) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // ExecStopContainer is not available as the runtime is missing.
 | |
| // TODO: We can also investigate using unix.Kill() on the PID of the exec
 | |
| // session here if we want to make stopping containers possible. Won't be
 | |
| // perfect, though.
 | |
| func (r *MissingRuntime) ExecStopContainer(ctr *Container, sessionID string, timeout uint) error {
 | |
| 	return r.printError()
 | |
| }
 | |
| 
 | |
| // ExecUpdateStatus is not available as the runtime is missing.
 | |
| func (r *MissingRuntime) ExecUpdateStatus(ctr *Container, sessionID string) (bool, error) {
 | |
| 	return false, r.printError()
 | |
| }
 | |
| 
 | |
| // CheckpointContainer is not available as the runtime is missing
 | |
| func (r *MissingRuntime) CheckpointContainer(ctr *Container, options ContainerCheckpointOptions) (int64, error) {
 | |
| 	return 0, r.printError()
 | |
| }
 | |
| 
 | |
| // CheckConmonRunning is not available as the runtime is missing
 | |
| func (r *MissingRuntime) CheckConmonRunning(ctr *Container) (bool, error) {
 | |
| 	return false, r.printError()
 | |
| }
 | |
| 
 | |
| // SupportsCheckpoint returns false as checkpointing requires a working runtime
 | |
| func (r *MissingRuntime) SupportsCheckpoint() bool {
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // SupportsJSONErrors returns false as there is no runtime to give errors
 | |
| func (r *MissingRuntime) SupportsJSONErrors() bool {
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // SupportsNoCgroups returns false as there is no runtime to create containers
 | |
| func (r *MissingRuntime) SupportsNoCgroups() bool {
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // SupportsKVM checks if the OCI runtime supports running containers
 | |
| // without KVM separation
 | |
| func (r *MissingRuntime) SupportsKVM() bool {
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // AttachSocketPath does not work as there is no runtime to attach to.
 | |
| // (Theoretically we could follow ExitFilePath but there is no guarantee the
 | |
| // container is running and thus has an attach socket...)
 | |
| func (r *MissingRuntime) AttachSocketPath(ctr *Container) (string, error) {
 | |
| 	return "", r.printError()
 | |
| }
 | |
| 
 | |
| // ExecAttachSocketPath does not work as there is no runtime to attach to.
 | |
| // (Again, we could follow ExitFilePath, but no guarantee there is an existing
 | |
| // and running exec session)
 | |
| func (r *MissingRuntime) ExecAttachSocketPath(ctr *Container, sessionID string) (string, error) {
 | |
| 	return "", r.printError()
 | |
| }
 | |
| 
 | |
| // ExitFilePath returns the exit file path for containers.
 | |
| // Here, we mimic what ConmonOCIRuntime does, because there is a chance that the
 | |
| // container in question is still running happily (config file modified to
 | |
| // remove a runtime, for example). We can't find the runtime to do anything to
 | |
| // the container, but Conmon should still place an exit file for it.
 | |
| func (r *MissingRuntime) ExitFilePath(ctr *Container) (string, error) {
 | |
| 	if ctr == nil {
 | |
| 		return "", fmt.Errorf("must provide a valid container to get exit file path: %w", define.ErrInvalidArg)
 | |
| 	}
 | |
| 	return filepath.Join(r.exitsDir, ctr.ID()), nil
 | |
| }
 | |
| 
 | |
| // OOMFilePath returns the oom file path for a container.
 | |
| // The oom file will only exist if the container was oom killed.
 | |
| func (r *MissingRuntime) OOMFilePath(ctr *Container) (string, error) {
 | |
| 	return filepath.Join(r.persistDir, ctr.ID(), "oom"), nil
 | |
| }
 | |
| 
 | |
| // RuntimeInfo returns information on the missing runtime
 | |
| func (r *MissingRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) {
 | |
| 	ocirt := define.OCIRuntimeInfo{
 | |
| 		Name:    r.name,
 | |
| 		Path:    "missing",
 | |
| 		Package: "missing",
 | |
| 		Version: "missing",
 | |
| 	}
 | |
| 	return nil, &ocirt, nil
 | |
| }
 | |
| 
 | |
| // Return an error indicating the runtime is missing
 | |
| func (r *MissingRuntime) printError() error {
 | |
| 	return fmt.Errorf("runtime %s is missing: %w", r.name, define.ErrOCIRuntimeNotFound)
 | |
| }
 |