aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2019-04-15 22:03:47 +0200
committerGiuseppe Scrivano <gscrivan@redhat.com>2019-04-26 22:23:45 +0200
commit525f0b30ac280565a1f98fd4208821a4984a7515 (patch)
tree795c0e3bac1f9baf11fd6ecfbebf73518f5009f1
parentb6e2cbad0a4581a8fe4954ff4a9202461a526781 (diff)
downloadpodman-525f0b30ac280565a1f98fd4208821a4984a7515.tar.gz
podman-525f0b30ac280565a1f98fd4208821a4984a7515.tar.bz2
podman-525f0b30ac280565a1f98fd4208821a4984a7515.zip
system: add new subcommand "migrate"
it is useful to migrate existing containers to a new version of podman. Currently, it is needed to migrate rootless containers that were created with podman <= 1.2 to a newer version which requires all containers to be running in the same user namespace. Closes: https://github.com/containers/libpod/issues/2935 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r--cmd/podman/cliconfig/config.go4
-rw-r--r--cmd/podman/commands.go1
-rw-r--r--cmd/podman/libpodruntime/runtime.go14
-rw-r--r--cmd/podman/main_local.go2
-rw-r--r--cmd/podman/system_migrate.go50
-rw-r--r--docs/podman-system-migrate.1.md21
-rw-r--r--docs/podman-system.1.md1
-rw-r--r--libpod/options.go16
-rw-r--r--libpod/runtime.go20
-rw-r--r--libpod/runtime_migrate.go48
10 files changed, 173 insertions, 4 deletions
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index 640a4bff4..77156f47a 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -581,6 +581,10 @@ type SystemRenumberValues struct {
PodmanCommand
}
+type SystemMigrateValues struct {
+ PodmanCommand
+}
+
type SystemDfValues struct {
PodmanCommand
Verbose bool
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index c43ecec5c..36c28696f 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -77,6 +77,7 @@ func getSystemSubCommands() []*cobra.Command {
_pruneSystemCommand,
_renumberCommand,
_dfSystemCommand,
+ _migrateCommand,
}
}
diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go
index 78adf1252..595f8267f 100644
--- a/cmd/podman/libpodruntime/runtime.go
+++ b/cmd/podman/libpodruntime/runtime.go
@@ -9,17 +9,22 @@ import (
"github.com/pkg/errors"
)
+// GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers
+func GetRuntimeMigrate(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
+ return getRuntime(c, false, true)
+}
+
// GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber
func GetRuntimeRenumber(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(c, true)
+ return getRuntime(c, true, false)
}
// GetRuntime generates a new libpod runtime configured by command line options
func GetRuntime(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(c, false)
+ return getRuntime(c, false, false)
}
-func getRuntime(c *cliconfig.PodmanCommand, renumber bool) (*libpod.Runtime, error) {
+func getRuntime(c *cliconfig.PodmanCommand, renumber bool, migrate bool) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
storageOpts := storage.StoreOptions{}
storageSet := false
@@ -63,6 +68,9 @@ func getRuntime(c *cliconfig.PodmanCommand, renumber bool) (*libpod.Runtime, err
storageSet = true
storageOpts.GraphDriverOptions = c.GlobalFlags.StorageOpts
}
+ if migrate {
+ options = append(options, libpod.WithMigrate())
+ }
if renumber {
options = append(options, libpod.WithRenumber())
diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go
index 91ad42630..42a8e434e 100644
--- a/cmd/podman/main_local.go
+++ b/cmd/podman/main_local.go
@@ -103,7 +103,7 @@ func profileOff(cmd *cobra.Command) error {
}
func setupRootless(cmd *cobra.Command, args []string) error {
- if os.Geteuid() == 0 || cmd == _searchCommand || cmd == _versionCommand || cmd == _mountCommand || strings.HasPrefix(cmd.Use, "help") {
+ if os.Geteuid() == 0 || cmd == _searchCommand || cmd == _versionCommand || cmd == _mountCommand || cmd == _migrateCommand || strings.HasPrefix(cmd.Use, "help") {
return nil
}
podmanCmd := cliconfig.PodmanCommand{
diff --git a/cmd/podman/system_migrate.go b/cmd/podman/system_migrate.go
new file mode 100644
index 000000000..b08eedcde
--- /dev/null
+++ b/cmd/podman/system_migrate.go
@@ -0,0 +1,50 @@
+package main
+
+import (
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ migrateCommand cliconfig.SystemMigrateValues
+ migrateDescription = `
+ podman system migrate
+
+ Migrate existing containers to a new version of Podman.
+`
+
+ _migrateCommand = &cobra.Command{
+ Use: "migrate",
+ Args: noSubArgs,
+ Short: "Migrate containers",
+ Long: migrateDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ migrateCommand.InputArgs = args
+ migrateCommand.GlobalFlags = MainGlobalOpts
+ return migrateCmd(&migrateCommand)
+ },
+ }
+)
+
+func init() {
+ migrateCommand.Command = _migrateCommand
+ migrateCommand.SetHelpTemplate(HelpTemplate())
+ migrateCommand.SetUsageTemplate(UsageTemplate())
+}
+
+func migrateCmd(c *cliconfig.SystemMigrateValues) error {
+ // We need to pass one extra option to NewRuntime.
+ // This will inform the OCI runtime to start a migrate.
+ // That's controlled by the last argument to GetRuntime.
+ r, err := libpodruntime.GetRuntimeMigrate(&c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "error migrating containers")
+ }
+ if err := r.Shutdown(false); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/docs/podman-system-migrate.1.md b/docs/podman-system-migrate.1.md
new file mode 100644
index 000000000..7c2d1823c
--- /dev/null
+++ b/docs/podman-system-migrate.1.md
@@ -0,0 +1,21 @@
+% podman-system-migrate(1) podman
+
+## NAME
+podman\-system\-migrate - Migrate container to the latest version of podman
+
+## SYNOPSIS
+** podman system migrate**
+
+## DESCRIPTION
+** podman system migrate** migrates containers to the latest podman version.
+
+**podman system migrate** takes care of migrating existing containers to the latest version of podman if any change is necessary.
+
+## SYNOPSIS
+**podman system migrate**
+
+## SEE ALSO
+`podman(1)`, `libpod.conf(5)`
+
+# HISTORY
+April 2019, Originally compiled by Giuseppe Scrivano (gscrivan at redhat dot com)
diff --git a/docs/podman-system.1.md b/docs/podman-system.1.md
index 32b3efdd9..d36715feb 100644
--- a/docs/podman-system.1.md
+++ b/docs/podman-system.1.md
@@ -17,6 +17,7 @@ The system command allows you to manage the podman systems
| info | [podman-system-info(1)](podman-info.1.md) | Displays Podman related system information. |
| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused data |
| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md)| Migrate lock numbers to handle a change in maximum number of locks. |
+| migrate | [podman-system-migrate(1)](podman-system-migrate.1.md)| Migrate existing containers to a new podman version. |
## SEE ALSO
podman(1)
diff --git a/libpod/options.go b/libpod/options.go
index 8038f1935..949894dcb 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -436,6 +436,22 @@ func WithRenumber() RuntimeOption {
}
}
+// WithMigrate instructs libpod to perform a lock migrateing while
+// initializing. This will handle migrations from early versions of libpod with
+// file locks to newer versions with SHM locking, as well as changes in the
+// number of configured locks.
+func WithMigrate() RuntimeOption {
+ return func(rt *Runtime) error {
+ if rt.valid {
+ return ErrRuntimeFinalized
+ }
+
+ rt.doMigrate = true
+
+ return nil
+ }
+}
+
// Container Creation Options
// WithShmDir sets the directory that should be mounted on /dev/shm.
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 69cc10389..6d279a107 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -100,6 +100,8 @@ type Runtime struct {
// unused.
doRenumber bool
+ doMigrate bool
+
// valid indicates whether the runtime is ready to use.
// valid is set to true when a runtime is returned from GetRuntime(),
// and remains true until the runtime is shut down (rendering its
@@ -962,6 +964,24 @@ func makeRuntime(runtime *Runtime) (err error) {
// further
runtime.valid = true
+ if runtime.doMigrate {
+ if os.Geteuid() != 0 {
+ aliveLock.Unlock()
+ locked = false
+
+ became, ret, err := rootless.BecomeRootInUserNS()
+ if err != nil {
+ return err
+ }
+ if became {
+ os.Exit(ret)
+ }
+ }
+ if err := runtime.migrate(); err != nil {
+ return err
+ }
+ }
+
return nil
}
diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go
new file mode 100644
index 000000000..7d7fa108d
--- /dev/null
+++ b/libpod/runtime_migrate.go
@@ -0,0 +1,48 @@
+package libpod
+
+import (
+ "context"
+ "path/filepath"
+
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+func (r *Runtime) migrate() 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 {
+ logrus.Infof("stopping %s", ctr.ID())
+ if err := ctr.Stop(); err != nil {
+ return errors.Wrapf(err, "cannot stop container %s", ctr.ID())
+ }
+ }
+
+ for _, ctr := range allCtrs {
+ 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")
+ if err := r.state.RewriteContainerConfig(ctr, ctr.config); err != nil {
+ return errors.Wrapf(err, "error rewriting config for container %s", ctr.ID())
+ }
+ }
+ }
+
+ for _, ctr := range runningContainers {
+ if err := ctr.Start(context.Background(), true); err != nil {
+ logrus.Errorf("error restarting container %s", ctr.ID())
+ }
+ }
+
+ return nil
+}