aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2018-12-11 10:22:34 +0100
committerGiuseppe Scrivano <gscrivan@redhat.com>2018-12-11 10:24:06 +0100
commit9a7416c3426d6fbad1205f333b8b2c6da4908be2 (patch)
tree865443909bc352fa480a319b0a156a7e79e9c0b1 /cmd
parent235a6300744636f650728f2a7545243aed045c91 (diff)
downloadpodman-9a7416c3426d6fbad1205f333b8b2c6da4908be2.tar.gz
podman-9a7416c3426d6fbad1205f333b8b2c6da4908be2.tar.bz2
podman-9a7416c3426d6fbad1205f333b8b2c6da4908be2.zip
rootless: fix restart when using fuse-overlayfs
With rootless containers we cannot really restart an existing container as we would need to join the mount namespace as well to be able to reuse the storage, so ensure the container is stopped first. Closes: https://github.com/containers/libpod/issues/1965 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/main.go1
-rw-r--r--cmd/podman/restart.go81
2 files changed, 75 insertions, 7 deletions
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 280448dc8..796b0b03a 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -36,6 +36,7 @@ var cmdsNotRequiringRootless = map[string]bool{
"logout": true,
"kill": true,
"pause": true,
+ "restart": true,
"run": true,
"unpause": true,
"search": true,
diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go
index 630493ef4..c6fe1025a 100644
--- a/cmd/podman/restart.go
+++ b/cmd/podman/restart.go
@@ -1,9 +1,13 @@
package main
import (
+ "fmt"
+ "os"
+
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
@@ -47,6 +51,10 @@ func restartCmd(c *cli.Context) error {
restartContainers []*libpod.Container
)
+ if os.Geteuid() != 0 {
+ rootless.SetSkipStorageSetup(true)
+ }
+
args := c.Args()
runOnly := c.Bool("running")
all := c.Bool("all")
@@ -95,6 +103,29 @@ func restartCmd(c *cli.Context) error {
}
}
+ maxWorkers := shared.Parallelize("restart")
+ if c.GlobalIsSet("max-workers") {
+ maxWorkers = c.GlobalInt("max-workers")
+ }
+
+ logrus.Debugf("Setting maximum workers to %d", maxWorkers)
+
+ if rootless.IsRootless() {
+ // With rootless containers we cannot really restart an existing container
+ // as we would need to join the mount namespace as well to be able to reuse
+ // the storage.
+ if err := stopRootlessContainers(restartContainers, timeout, useTimeout, maxWorkers); err != nil {
+ return err
+ }
+ became, ret, err := rootless.BecomeRootInUserNS()
+ if err != nil {
+ return err
+ }
+ if became {
+ os.Exit(ret)
+ }
+ }
+
// We now have a slice of all the containers to be restarted. Iterate them to
// create restart Funcs with a timeout as needed
for _, ctr := range restartContainers {
@@ -114,13 +145,49 @@ func restartCmd(c *cli.Context) error {
})
}
- maxWorkers := shared.Parallelize("restart")
- if c.GlobalIsSet("max-workers") {
- maxWorkers = c.GlobalInt("max-workers")
- }
-
- logrus.Debugf("Setting maximum workers to %d", maxWorkers)
-
restartErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, restartFuncs)
return printParallelOutput(restartErrors, errCount)
}
+
+func stopRootlessContainers(stopContainers []*libpod.Container, timeout uint, useTimeout bool, maxWorkers int) error {
+ var stopFuncs []shared.ParallelWorkerInput
+ for _, ctr := range stopContainers {
+ state, err := ctr.State()
+ if err != nil {
+ return err
+ }
+ if state != libpod.ContainerStateRunning {
+ continue
+ }
+
+ ctrTimeout := ctr.StopTimeout()
+ if useTimeout {
+ ctrTimeout = timeout
+ }
+
+ c := ctr
+ f := func() error {
+ return c.StopWithTimeout(ctrTimeout)
+ }
+
+ stopFuncs = append(stopFuncs, shared.ParallelWorkerInput{
+ ContainerID: c.ID(),
+ ParallelFunc: f,
+ })
+
+ restartErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, stopFuncs)
+ var lastError error
+ for _, result := range restartErrors {
+ if result != nil {
+ if errCount > 1 {
+ fmt.Println(result.Error())
+ }
+ lastError = result
+ }
+ }
+ if lastError != nil {
+ return lastError
+ }
+ }
+ return nil
+}