mirror of
https://github.com/containers/podman.git
synced 2025-05-17 15:18:43 +08:00

Previously, we always computed pause path from the Rootless runtime directory. Problem: this does not match the behavior of Libpod when the directory changes. Libpod will continue to use the previous directory, cached in the database; Pause pidfiles will swap to the new path. This is problematic when the directory needs to exist to write the pidfile, and Libpod is what creates the directory. There are two potential solutions - allow the pause pidfile to move and just make the directory when we want to write it, or use the cached Libpod paths for a guaranteed location. This patch does the second, because it seems safer - we will never miss a previously-existing pidfile because the location is now consistent. Fixes #8539 Signed-off-by: Matthew Heon <mheon@redhat.com>
103 lines
2.7 KiB
Go
103 lines
2.7 KiB
Go
// +build linux
|
|
|
|
package libpod
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"syscall"
|
|
|
|
"github.com/containers/podman/v2/libpod/define"
|
|
"github.com/containers/podman/v2/pkg/rootless"
|
|
"github.com/containers/podman/v2/pkg/util"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (r *Runtime) stopPauseProcess() error {
|
|
if rootless.IsRootless() {
|
|
pausePidPath, err := util.GetRootlessPauseProcessPidPathGivenDir(r.config.Engine.TmpDir)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not get pause process pid file path")
|
|
}
|
|
data, err := ioutil.ReadFile(pausePidPath)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return nil
|
|
}
|
|
return errors.Wrap(err, "cannot read pause process pid file")
|
|
}
|
|
pausePid, err := strconv.Atoi(string(data))
|
|
if err != nil {
|
|
return errors.Wrapf(err, "cannot parse pause pid file %s", pausePidPath)
|
|
}
|
|
if err := os.Remove(pausePidPath); err != nil {
|
|
return errors.Wrapf(err, "cannot delete pause pid file %s", pausePidPath)
|
|
}
|
|
if err := syscall.Kill(pausePid, syscall.SIGKILL); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *Runtime) migrate(ctx context.Context) error {
|
|
runningContainers, err := r.GetRunningContainers()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
allCtrs, err := r.state.AllContainers()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
logrus.Infof("stopping all containers")
|
|
for _, ctr := range runningContainers {
|
|
fmt.Printf("stopped %s\n", ctr.ID())
|
|
if err := ctr.Stop(); err != nil {
|
|
return errors.Wrapf(err, "cannot stop container %s", ctr.ID())
|
|
}
|
|
}
|
|
|
|
// Did the user request a new runtime?
|
|
runtimeChangeRequested := r.migrateRuntime != ""
|
|
requestedRuntime, runtimeExists := r.ociRuntimes[r.migrateRuntime]
|
|
if !runtimeExists && runtimeChangeRequested {
|
|
return errors.Wrapf(define.ErrInvalidArg, "change to runtime %q requested but no such runtime is defined", r.migrateRuntime)
|
|
}
|
|
|
|
for _, ctr := range allCtrs {
|
|
needsWrite := false
|
|
|
|
// Reset pause process location
|
|
oldLocation := filepath.Join(ctr.state.RunDir, "conmon.pid")
|
|
if ctr.config.ConmonPidFile == oldLocation {
|
|
logrus.Infof("changing conmon PID file for %s", ctr.ID())
|
|
ctr.config.ConmonPidFile = filepath.Join(ctr.config.StaticDir, "conmon.pid")
|
|
needsWrite = true
|
|
}
|
|
|
|
// Reset runtime
|
|
if runtimeChangeRequested {
|
|
logrus.Infof("Resetting container %s runtime to runtime %s", ctr.ID(), r.migrateRuntime)
|
|
ctr.config.OCIRuntime = r.migrateRuntime
|
|
ctr.ociRuntime = requestedRuntime
|
|
|
|
needsWrite = true
|
|
}
|
|
|
|
if needsWrite {
|
|
if err := r.state.RewriteContainerConfig(ctr, ctr.config); err != nil {
|
|
return errors.Wrapf(err, "error rewriting config for container %s", ctr.ID())
|
|
}
|
|
}
|
|
}
|
|
|
|
return r.stopPauseProcess()
|
|
}
|