Merge pull request from mheon/reset_runtime

Migrate can move containers to a user-defined runtime
This commit is contained in:
OpenShift Merge Robot
2019-10-11 19:56:13 +02:00
committed by GitHub
7 changed files with 73 additions and 9 deletions

@ -651,6 +651,7 @@ type SystemRenumberValues struct {
type SystemMigrateValues struct { type SystemMigrateValues struct {
PodmanCommand PodmanCommand
NewRuntime string
} }
type SystemDfValues struct { type SystemDfValues struct {

@ -14,31 +14,31 @@ import (
) )
// GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers // GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers
func GetRuntimeMigrate(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { func GetRuntimeMigrate(ctx context.Context, c *cliconfig.PodmanCommand, newRuntime string) (*libpod.Runtime, error) {
return getRuntime(ctx, c, false, true, false, true) return getRuntime(ctx, c, false, true, false, true, newRuntime)
} }
// GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify // GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify
func GetRuntimeDisableFDs(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { func GetRuntimeDisableFDs(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
return getRuntime(ctx, c, false, false, false, false) return getRuntime(ctx, c, false, false, false, false, "")
} }
// GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber // GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber
func GetRuntimeRenumber(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { func GetRuntimeRenumber(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
return getRuntime(ctx, c, true, false, false, true) return getRuntime(ctx, c, true, false, false, true, "")
} }
// GetRuntime generates a new libpod runtime configured by command line options // GetRuntime generates a new libpod runtime configured by command line options
func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
return getRuntime(ctx, c, false, false, false, true) return getRuntime(ctx, c, false, false, false, true, "")
} }
// GetRuntimeNoStore generates a new libpod runtime configured by command line options // GetRuntimeNoStore generates a new libpod runtime configured by command line options
func GetRuntimeNoStore(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { func GetRuntimeNoStore(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
return getRuntime(ctx, c, false, false, true, true) return getRuntime(ctx, c, false, false, true, true, "")
} }
func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migrate, noStore, withFDS bool) (*libpod.Runtime, error) { func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migrate, noStore, withFDS bool, newRuntime string) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{} options := []libpod.RuntimeOption{}
storageOpts := storage.StoreOptions{} storageOpts := storage.StoreOptions{}
storageSet := false storageSet := false
@ -88,6 +88,9 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra
} }
if migrate { if migrate {
options = append(options, libpod.WithMigrate()) options = append(options, libpod.WithMigrate())
if newRuntime != "" {
options = append(options, libpod.WithMigrateRuntime(newRuntime))
}
} }
if renumber { if renumber {

@ -32,13 +32,15 @@ func init() {
migrateCommand.Command = _migrateCommand migrateCommand.Command = _migrateCommand
migrateCommand.SetHelpTemplate(HelpTemplate()) migrateCommand.SetHelpTemplate(HelpTemplate())
migrateCommand.SetUsageTemplate(UsageTemplate()) migrateCommand.SetUsageTemplate(UsageTemplate())
flags := migrateCommand.Flags()
flags.StringVar(&migrateCommand.NewRuntime, "new-runtime", "", "Specify a new runtime for all containers")
} }
func migrateCmd(c *cliconfig.SystemMigrateValues) error { func migrateCmd(c *cliconfig.SystemMigrateValues) error {
// We need to pass one extra option to NewRuntime. // We need to pass one extra option to NewRuntime.
// This will inform the OCI runtime to start a migrate. // This will inform the OCI runtime to start a migrate.
// That's controlled by the last argument to GetRuntime. // That's controlled by the last argument to GetRuntime.
r, err := libpodruntime.GetRuntimeMigrate(getContext(), &c.PodmanCommand) r, err := libpodruntime.GetRuntimeMigrate(getContext(), &c.PodmanCommand, c.NewRuntime)
if err != nil { if err != nil {
return errors.Wrapf(err, "error migrating containers") return errors.Wrapf(err, "error migrating containers")
} }

@ -24,6 +24,14 @@ pause process. The `/etc/subuid` and `/etc/subgid` files can then be
edited or changed with usermod to recreate the user namespace with the edited or changed with usermod to recreate the user namespace with the
newly configured mappings. newly configured mappings.
## OPTIONS
**--new-runtime**=*runtime*
Set a new OCI runtime for all containers.
This can be used after a system upgrade which changes the default OCI runtime to move all containers to the new runtime.
There are no guarantees that the containers will continue to work under the new runtime, as some runtimes support differing options and configurations.
## SYNOPSIS ## SYNOPSIS
**podman system migrate** **podman system migrate**

@ -463,6 +463,28 @@ func WithMigrate() RuntimeOption {
} }
} }
// WithMigrateRuntime instructs Libpod to change the default OCI runtime on all
// containers during a migration. This is not used if `MigrateRuntime()` is not
// also passed.
// Libpod makes no promises that your containers continue to work with the new
// runtime - migrations between dissimilar runtimes may well break things.
// Use with caution.
func WithMigrateRuntime(requestedRuntime string) RuntimeOption {
return func(rt *Runtime) error {
if rt.valid {
return define.ErrRuntimeFinalized
}
if requestedRuntime == "" {
return errors.Wrapf(define.ErrInvalidArg, "must provide a non-empty name for new runtime")
}
rt.migrateRuntime = requestedRuntime
return nil
}
}
// WithEventsLogger sets the events backend to use. // WithEventsLogger sets the events backend to use.
// Currently supported values are "file" for file backend and "journald" for // Currently supported values are "file" for file backend and "journald" for
// journald backend. // journald backend.

@ -114,6 +114,10 @@ type Runtime struct {
doRenumber bool doRenumber bool
doMigrate bool doMigrate bool
// System migrate can move containers to a new runtime.
// We make no promises that these migrated containers work on the new
// runtime, though.
migrateRuntime string
// valid indicates whether the runtime is ready to use. // valid indicates whether the runtime is ready to use.
// valid is set to true when a runtime is returned from GetRuntime(), // valid is set to true when a runtime is returned from GetRuntime(),

@ -5,14 +5,15 @@ package libpod
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/containers/libpod/pkg/util"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
"syscall" "syscall"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -63,11 +64,34 @@ func (r *Runtime) migrate(ctx context.Context) error {
} }
} }
// 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 { for _, ctr := range allCtrs {
needsWrite := false
// Reset pause process location
oldLocation := filepath.Join(ctr.state.RunDir, "conmon.pid") oldLocation := filepath.Join(ctr.state.RunDir, "conmon.pid")
if ctr.config.ConmonPidFile == oldLocation { if ctr.config.ConmonPidFile == oldLocation {
logrus.Infof("changing conmon PID file for %s", ctr.ID()) logrus.Infof("changing conmon PID file for %s", ctr.ID())
ctr.config.ConmonPidFile = filepath.Join(ctr.config.StaticDir, "conmon.pid") 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 { if err := r.state.RewriteContainerConfig(ctr, ctr.config); err != nil {
return errors.Wrapf(err, "error rewriting config for container %s", ctr.ID()) return errors.Wrapf(err, "error rewriting config for container %s", ctr.ID())
} }