mirror of
https://github.com/containers/podman.git
synced 2025-12-08 14:48:48 +08:00
use a pause process to keep the user and mount namespace alive. The pause process is created immediately on reload, and all successive Podman processes will refer to it for joining the user&mount namespace. This solves all the race conditions we had on joining the correct namespaces using the conmon processes. As a fallback if the join fails for any reason (e.g. the pause process was killed), then we try to join the running containers as we were doing before. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
170 lines
4.4 KiB
Go
170 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
js "encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
of "github.com/containers/buildah/pkg/formats"
|
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
|
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
|
"github.com/containers/libpod/pkg/rootless"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
mountCommand cliconfig.MountValues
|
|
|
|
mountDescription = `podman mount
|
|
Lists all mounted containers mount points if no container is specified
|
|
|
|
podman mount CONTAINER-NAME-OR-ID
|
|
Mounts the specified container and outputs the mountpoint
|
|
`
|
|
|
|
_mountCommand = &cobra.Command{
|
|
Use: "mount [flags] [CONTAINER]",
|
|
Short: "Mount a working container's root filesystem",
|
|
Long: mountDescription,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
mountCommand.InputArgs = args
|
|
mountCommand.GlobalFlags = MainGlobalOpts
|
|
mountCommand.Remote = remoteclient
|
|
return mountCmd(&mountCommand)
|
|
},
|
|
Args: func(cmd *cobra.Command, args []string) error {
|
|
return checkAllAndLatest(cmd, args, true)
|
|
},
|
|
}
|
|
)
|
|
|
|
func init() {
|
|
mountCommand.Command = _mountCommand
|
|
mountCommand.SetHelpTemplate(HelpTemplate())
|
|
mountCommand.SetUsageTemplate(UsageTemplate())
|
|
flags := mountCommand.Flags()
|
|
flags.BoolVarP(&mountCommand.All, "all", "a", false, "Mount all containers")
|
|
flags.StringVar(&mountCommand.Format, "format", "", "Change the output format to Go template")
|
|
flags.BoolVarP(&mountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
|
flags.BoolVar(&mountCommand.NoTrunc, "notruncate", false, "Do not truncate output")
|
|
|
|
markFlagHiddenForRemoteClient("latest", flags)
|
|
}
|
|
|
|
// jsonMountPoint stores info about each container
|
|
type jsonMountPoint struct {
|
|
ID string `json:"id"`
|
|
Names []string `json:"names"`
|
|
MountPoint string `json:"mountpoint"`
|
|
}
|
|
|
|
func mountCmd(c *cliconfig.MountValues) error {
|
|
runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not get runtime")
|
|
}
|
|
defer runtime.Shutdown(false)
|
|
|
|
if os.Geteuid() != 0 {
|
|
rtc, err := runtime.GetConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if driver := rtc.StorageConfig.GraphDriverName; driver != "vfs" {
|
|
// Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part
|
|
// of the mount command.
|
|
return fmt.Errorf("cannot mount using driver %s in rootless mode", driver)
|
|
}
|
|
|
|
became, ret, err := rootless.BecomeRootInUserNS("")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if became {
|
|
os.Exit(ret)
|
|
}
|
|
}
|
|
|
|
if c.All && c.Latest {
|
|
return errors.Errorf("--all and --latest cannot be used together")
|
|
}
|
|
|
|
mountContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
|
|
if err != nil {
|
|
if len(mountContainers) == 0 {
|
|
return err
|
|
}
|
|
fmt.Println(err.Error())
|
|
}
|
|
|
|
formats := map[string]bool{
|
|
"": true,
|
|
of.JSONString: true,
|
|
}
|
|
|
|
json := c.Format == of.JSONString
|
|
if !formats[c.Format] {
|
|
return errors.Errorf("%q is not a supported format", c.Format)
|
|
}
|
|
|
|
var lastError error
|
|
if len(mountContainers) > 0 {
|
|
for _, ctr := range mountContainers {
|
|
if json {
|
|
if lastError != nil {
|
|
logrus.Error(lastError)
|
|
}
|
|
lastError = errors.Wrapf(err, "json option cannot be used with a container id")
|
|
continue
|
|
}
|
|
mountPoint, err := ctr.Mount()
|
|
if err != nil {
|
|
if lastError != nil {
|
|
logrus.Error(lastError)
|
|
}
|
|
lastError = errors.Wrapf(err, "error mounting container %q", ctr.ID())
|
|
continue
|
|
}
|
|
fmt.Printf("%s\n", mountPoint)
|
|
}
|
|
return lastError
|
|
} else {
|
|
jsonMountPoints := []jsonMountPoint{}
|
|
containers, err2 := runtime.GetContainers()
|
|
if err2 != nil {
|
|
return errors.Wrapf(err2, "error reading list of all containers")
|
|
}
|
|
for _, container := range containers {
|
|
mounted, mountPoint, err := container.Mounted()
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error getting mountpoint for %q", container.ID())
|
|
}
|
|
|
|
if !mounted {
|
|
continue
|
|
}
|
|
|
|
if json {
|
|
jsonMountPoints = append(jsonMountPoints, jsonMountPoint{ID: container.ID(), Names: []string{container.Name()}, MountPoint: mountPoint})
|
|
continue
|
|
}
|
|
|
|
if c.NoTrunc {
|
|
fmt.Printf("%-64s %s\n", container.ID(), mountPoint)
|
|
} else {
|
|
fmt.Printf("%-12.12s %s\n", container.ID(), mountPoint)
|
|
}
|
|
}
|
|
if json {
|
|
data, err := js.MarshalIndent(jsonMountPoints, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("%s\n", data)
|
|
}
|
|
}
|
|
return nil
|
|
}
|