summaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/common/create_opts.go2
-rw-r--r--cmd/podman/common/specgen.go64
-rw-r--r--cmd/podman/containers/create.go2
-rw-r--r--cmd/podman/images/mount.go139
-rw-r--r--cmd/podman/images/unmount.go71
5 files changed, 254 insertions, 24 deletions
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go
index 3802c37b0..f9e4d7ca5 100644
--- a/cmd/podman/common/create_opts.go
+++ b/cmd/podman/common/create_opts.go
@@ -10,7 +10,7 @@ type ContainerCLIOpts struct {
BlkIOWeightDevice []string
CapAdd []string
CapDrop []string
- CGroupsNS string
+ CgroupNS string
CGroupsMode string
CGroupParent string
CIDFile string
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go
index 07c88efea..0b6897d3a 100644
--- a/cmd/podman/common/specgen.go
+++ b/cmd/podman/common/specgen.go
@@ -186,6 +186,46 @@ func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts) (*specs.Linu
return memory, nil
}
+func setNamespaces(s *specgen.SpecGenerator, c *ContainerCLIOpts) error {
+ var err error
+
+ if c.PID != "" {
+ s.PidNS, err = specgen.ParseNamespace(c.PID)
+ if err != nil {
+ return err
+ }
+ }
+ if c.IPC != "" {
+ s.IpcNS, err = specgen.ParseNamespace(c.IPC)
+ if err != nil {
+ return err
+ }
+ }
+ if c.UTS != "" {
+ s.UtsNS, err = specgen.ParseNamespace(c.UTS)
+ if err != nil {
+ return err
+ }
+ }
+ if c.CgroupNS != "" {
+ s.CgroupNS, err = specgen.ParseNamespace(c.CgroupNS)
+ if err != nil {
+ return err
+ }
+ }
+ // userns must be treated differently
+ if c.UserNS != "" {
+ s.UserNS, err = specgen.ParseUserNamespace(c.UserNS)
+ if err != nil {
+ return err
+ }
+ }
+ if c.Net != nil {
+ s.NetNS = c.Net.Network
+ }
+ return nil
+}
+
func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) error {
var (
err error
@@ -252,28 +292,8 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
}
s.Expose = expose
- for k, v := range map[string]*specgen.Namespace{
- c.IPC: &s.IpcNS,
- c.PID: &s.PidNS,
- c.UTS: &s.UtsNS,
- c.CGroupsNS: &s.CgroupNS,
- } {
- if k != "" {
- *v, err = specgen.ParseNamespace(k)
- if err != nil {
- return err
- }
- }
- }
- // userns must be treated differently
- if c.UserNS != "" {
- s.UserNS, err = specgen.ParseUserNamespace(c.UserNS)
- if err != nil {
- return err
- }
- }
- if c.Net != nil {
- s.NetNS = c.Net.Network
+ if err := setNamespaces(s, c); err != nil {
+ return err
}
if sig := c.StopSignal; len(sig) > 0 {
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index dcbc52b56..dd77dc9d7 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -195,7 +195,7 @@ func createInit(c *cobra.Command) error {
cliVals.IPC = c.Flag("ipc").Value.String()
cliVals.UTS = c.Flag("uts").Value.String()
cliVals.PID = c.Flag("pid").Value.String()
- cliVals.CGroupsNS = c.Flag("cgroupns").Value.String()
+ cliVals.CgroupNS = c.Flag("cgroupns").Value.String()
if c.Flag("entrypoint").Changed {
val := c.Flag("entrypoint").Value.String()
cliVals.Entrypoint = &val
diff --git a/cmd/podman/images/mount.go b/cmd/podman/images/mount.go
new file mode 100644
index 000000000..fac06e324
--- /dev/null
+++ b/cmd/podman/images/mount.go
@@ -0,0 +1,139 @@
+package images
+
+import (
+ "fmt"
+ "os"
+ "text/tabwriter"
+ "text/template"
+
+ "github.com/containers/podman/v2/cmd/podman/registry"
+ "github.com/containers/podman/v2/cmd/podman/utils"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+var (
+ mountDescription = `podman image mount
+ Lists all mounted images mount points if no images is specified
+
+ podman image mount IMAGE-NAME-OR-ID
+ Mounts the specified image and prints the mountpoint
+`
+
+ mountCommand = &cobra.Command{
+ Use: "mount [flags] [IMAGE...]",
+ Short: "Mount an images's root filesystem",
+ Long: mountDescription,
+ RunE: mount,
+ Example: `podman image mount imgID
+ podman image mount imgID1 imgID2 imgID3
+ podman image mount
+ podman image mount --all`,
+ Annotations: map[string]string{
+ registry.UnshareNSRequired: "",
+ registry.ParentNSRequired: "",
+ },
+ }
+)
+
+var (
+ mountOpts entities.ImageMountOptions
+)
+
+func mountFlags(flags *pflag.FlagSet) {
+ flags.BoolVarP(&mountOpts.All, "all", "a", false, "Mount all images")
+ flags.StringVar(&mountOpts.Format, "format", "", "Print the mounted images in specified format (json)")
+}
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: mountCommand,
+ Parent: imageCmd,
+ })
+ mountFlags(mountCommand.Flags())
+}
+
+func mount(_ *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ if len(args) > 0 && mountOpts.All {
+ return errors.New("when using the --all switch, you may not pass any image names or IDs")
+ }
+ reports, err := registry.ImageEngine().Mount(registry.GetContext(), args, mountOpts)
+ if err != nil {
+ return err
+ }
+ if len(args) > 0 || mountOpts.All {
+ for _, r := range reports {
+ if r.Err == nil {
+ fmt.Println(r.Path)
+ continue
+ }
+ errs = append(errs, r.Err)
+ }
+ return errs.PrintErrors()
+ }
+
+ switch mountOpts.Format {
+ case "json":
+ return printJSON(reports)
+ case "":
+ // do nothing
+ default:
+ return errors.Errorf("unknown --format argument: %s", mountOpts.Format)
+ }
+
+ mrs := make([]mountReporter, 0, len(reports))
+ for _, r := range reports {
+ mrs = append(mrs, mountReporter{r})
+ }
+ row := "{{.ID}} {{.Path}}\n"
+ format := "{{range . }}" + row + "{{end}}"
+ tmpl, err := template.New("mounts").Parse(format)
+ if err != nil {
+ return err
+ }
+ w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+ defer w.Flush()
+ return tmpl.Execute(w, mrs)
+}
+
+func printJSON(reports []*entities.ImageMountReport) error {
+ type jreport struct {
+ ID string `json:"id"`
+ Names []string
+ Repositories []string
+ Mountpoint string `json:"mountpoint"`
+ }
+ jreports := make([]jreport, 0, len(reports))
+
+ for _, r := range reports {
+ jreports = append(jreports, jreport{
+ ID: r.Id,
+ Names: []string{r.Name},
+ Repositories: r.Repositories,
+ Mountpoint: r.Path,
+ })
+ }
+ b, err := json.MarshalIndent(jreports, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+}
+
+type mountReporter struct {
+ *entities.ImageMountReport
+}
+
+func (m mountReporter) ID() string {
+ if len(m.Repositories) > 0 {
+ return m.Repositories[0]
+ }
+ return m.Id
+}
diff --git a/cmd/podman/images/unmount.go b/cmd/podman/images/unmount.go
new file mode 100644
index 000000000..f7f6cf8e5
--- /dev/null
+++ b/cmd/podman/images/unmount.go
@@ -0,0 +1,71 @@
+package images
+
+import (
+ "fmt"
+
+ "github.com/containers/podman/v2/cmd/podman/registry"
+ "github.com/containers/podman/v2/cmd/podman/utils"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+var (
+ description = `Image storage increments a mount counter each time an image is mounted.
+
+ When an image is unmounted, the mount counter is decremented. The image's root filesystem is physically unmounted only when the mount counter reaches zero indicating no other processes are using the mount.
+
+ An unmount can be forced with the --force flag.
+`
+ unmountCommand = &cobra.Command{
+ Use: "unmount [flags] IMAGE [IMAGE...]",
+ Aliases: []string{"umount"},
+ Short: "Unmount an image's root filesystem",
+ Long: description,
+ RunE: unmount,
+ Example: `podman unmount imgID
+ podman unmount imgID1 imgID2 imgID3
+ podman unmount --all`,
+ }
+)
+
+var (
+ unmountOpts entities.ImageUnmountOptions
+)
+
+func unmountFlags(flags *pflag.FlagSet) {
+ flags.BoolVarP(&unmountOpts.All, "all", "a", false, "Unmount all of the currently mounted images")
+ flags.BoolVarP(&unmountOpts.Force, "force", "f", false, "Force the complete unmount of the specified mounted images")
+}
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Parent: imageCmd,
+ Command: unmountCommand,
+ })
+ unmountFlags(unmountCommand.Flags())
+}
+
+func unmount(cmd *cobra.Command, args []string) error {
+ var errs utils.OutputErrors
+ if len(args) < 1 && !unmountOpts.All {
+ return errors.New("image name or ID must be specified")
+ }
+ if len(args) > 0 && unmountOpts.All {
+ return errors.New("when using the --all switch, you may not pass any image names or IDs")
+ }
+ reports, err := registry.ImageEngine().Unmount(registry.GetContext(), args, unmountOpts)
+ if err != nil {
+ return err
+ }
+ for _, r := range reports {
+ if r.Err == nil {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Err)
+ }
+ }
+ return errs.PrintErrors()
+}