Merge pull request #694 from rhatdan/mount

Add kpod-mount and kpod-umount to mount and umount container images
This commit is contained in:
Mrunal Patel 2017-08-08 13:55:01 -07:00 committed by GitHub
commit 8e394e0589
9 changed files with 328 additions and 5 deletions

View file

@ -26,10 +26,12 @@ func main() {
imagesCommand, imagesCommand,
infoCommand, infoCommand,
inspectCommand, inspectCommand,
mountCommand,
pullCommand, pullCommand,
pushCommand, pushCommand,
rmiCommand, rmiCommand,
tagCommand, tagCommand,
umountCommand,
versionCommand, versionCommand,
saveCommand, saveCommand,
loadCommand, loadCommand,

117
cmd/kpod/mount.go Normal file
View file

@ -0,0 +1,117 @@
package main
import (
js "encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
mountDescription = `
kpod mount
Lists all mounted containers mount points
kpod mount CONTAINER-NAME-OR-ID
Mounts the specified container and outputs the mountpoint
`
mountFlags = []cli.Flag{
cli.BoolFlag{
Name: "notruncate",
Usage: "do not truncate output",
},
cli.StringFlag{
Name: "label",
Usage: "SELinux label for the mount point",
},
cli.StringFlag{
Name: "format",
Usage: "Print mounted containers in specified format",
},
}
mountCommand = cli.Command{
Name: "mount",
Usage: "Mount a working container's root filesystem",
Description: mountDescription,
Action: mountCmd,
ArgsUsage: "[CONTAINER-NAME-OR-ID]",
Flags: mountFlags,
}
)
// MountOutputParams stores info about each layer
type jsonMountPoint struct {
ID string `json:"id"`
Names []string `json:"names"`
MountPoint string `json:"mountpoint"`
}
func mountCmd(c *cli.Context) error {
formats := map[string]bool{
"": true,
"json": true,
}
args := c.Args()
json := c.String("format") == "json"
if !formats[c.String("format")] {
return errors.Errorf("%q is not a supported format", c.String("format"))
}
if len(args) > 1 {
return errors.Errorf("too many arguments specified")
}
config, err := getConfig(c)
if err != nil {
return errors.Wrapf(err, "Could not get config")
}
store, err := getStore(config)
if err != nil {
return errors.Wrapf(err, "error getting store")
}
if len(args) == 1 {
if json {
return errors.Wrapf(err, "json option can not be used with a container id")
}
mountPoint, err := store.Mount(args[0], c.String("label"))
if err != nil {
return errors.Wrapf(err, "error finding container %q", args[0])
}
fmt.Printf("%s\n", mountPoint)
} else {
jsonMountPoints := []jsonMountPoint{}
containers, err2 := store.Containers()
if err2 != nil {
return errors.Wrapf(err2, "error reading list of all containers")
}
for _, container := range containers {
layer, err := store.Layer(container.LayerID)
if err != nil {
return errors.Wrapf(err, "error finding layer %q for container %q", container.LayerID, container.ID)
}
if layer.MountPoint == "" {
continue
}
if json {
jsonMountPoints = append(jsonMountPoints, jsonMountPoint{ID: container.ID, Names: container.Names, MountPoint: layer.MountPoint})
continue
}
if c.Bool("notruncate") {
fmt.Printf("%-64s %s\n", container.ID, layer.MountPoint)
} else {
fmt.Printf("%-12.12s %s\n", container.ID, layer.MountPoint)
}
}
if json {
data, err := js.MarshalIndent(jsonMountPoints, "", " ")
if err != nil {
return err
}
fmt.Printf("%s\n", data)
}
}
return nil
}

41
cmd/kpod/umount.go Normal file
View file

@ -0,0 +1,41 @@
package main
import (
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
umountCommand = cli.Command{
Name: "umount",
Aliases: []string{"unmount"},
Usage: "Unmount a working container's root filesystem",
Description: "Unmounts a working container's root filesystem",
Action: umountCmd,
ArgsUsage: "CONTAINER-NAME-OR-ID",
}
)
func umountCmd(c *cli.Context) error {
args := c.Args()
if len(args) == 0 {
return errors.Errorf("container ID must be specified")
}
if len(args) > 1 {
return errors.Errorf("too many arguments specified")
}
config, err := getConfig(c)
if err != nil {
return errors.Wrapf(err, "Could not get config")
}
store, err := getStore(config)
if err != nil {
return err
}
err = store.Unmount(args[0])
if err != nil {
return errors.Wrapf(err, "error unmounting container %q", args[0])
}
return nil
}

View file

@ -71,6 +71,48 @@ _kpod_pull() {
_complete_ "$options_with_args" "$boolean_options" _complete_ "$options_with_args" "$boolean_options"
} }
_kpod_unmount() {
_kpod_umount $@
}
_kpod_umount() {
local boolean_options="
--help
-h
"
local options_with_args="
"
local all_options="$options_with_args $boolean_options"
case "$cur" in
-*)
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
;;
esac
}
_kpod_mount() {
local boolean_options="
--help
-h
--notruncate
"
local options_with_args="
--label
--format
"
local all_options="$options_with_args $boolean_options"
case "$cur" in
-*)
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
;;
esac
}
_kpod_push() { _kpod_push() {
local boolean_options=" local boolean_options="
--disable-compression --disable-compression
@ -175,15 +217,18 @@ _kpod_kpod() {
--help -h --help -h
" "
commands=" commands="
history
images images
launch launch
load
mount
pull
push push
rmi rmi
tag tag
umount
unmount
version version
pull
history
load
" "
case "$prev" in case "$prev" in

50
docs/kpod-mount.1.md Normal file
View file

@ -0,0 +1,50 @@
% kpod(1) kpod-mount - Mount a working container's root filesystem.
% Dan Walsh
# kpod-mount "1" "July 2017" "kpod"
## NAME
kpod mount - Mount a working container's root filesystem.
## SYNOPSIS
**kpod** **mount**
**kpod** **mount** **containerID**
## DESCRIPTION
Mounts the specified container's root file system in a location which can be
accessed from the host, and returns its location.
If you execute the command without any arguments, the tool will list all of the
currently mounted containers.
## RETURN VALUE
The location of the mounted file system. On error an empty string and errno is
returned.
## OPTIONS
**--format**
Print the mounted containers in specified format (json)
**--notruncate**
Do not truncate IDs in output.
**--label**
SELinux label for the mount point
## EXAMPLE
kpod mount c831414b10a3
/var/lib/containers/storage/overlay2/f3ac502d97b5681989dff84dfedc8354239bcecbdc2692f9a639f4e080a02364/merged
kpod mount
c831414b10a3 /var/lib/containers/storage/overlay2/f3ac502d97b5681989dff84dfedc8354239bcecbdc2692f9a639f4e080a02364/merged
a7060253093b /var/lib/containers/storage/overlay2/0ff7d7ca68bed1ace424f9df154d2dd7b5a125c19d887f17653cbcd5b6e30ba1/merged
## SEE ALSO
kpod(1), kpod-umount(1), mount(8)

View file

@ -10,7 +10,7 @@ kpod push - Push an image from local storage to elsewhere
## DESCRIPTION ## DESCRIPTION
Pushes an image from local storage to a specified destination, decompressing Pushes an image from local storage to a specified destination, decompressing
and recompessing layers as needed. and recompressing layers as needed.
## imageID ## imageID
Image stored in local container/storage Image stored in local container/storage

19
docs/kpod-umount.1.md Normal file
View file

@ -0,0 +1,19 @@
% kpod(1) kpod-umount - Unmount a working container's root filesystem.
% Dan Walsh
# kpod-umount "1" "July 2017" "kpod"
## NAME
kpod umount - Unmount a working container's root file system.
## SYNOPSIS
**kpod** **umount** **containerID**
## DESCRIPTION
Unmounts the specified container's root file system.
## EXAMPLE
kpod umount containerID
## SEE ALSO
kpod(1), kpod-mount(1)

View file

@ -18,7 +18,7 @@ function teardown() {
} }
@test "kpod pull from docker with tag" { @test "kpod pull from docker with tag" {
run ${KPOD_BINARY} $KPOD_OPTIONS pull debian:6.0.10 run ${KPOD_BINARY} ${KPOD_OPTIONS} pull debian:6.0.10
echo "$output" echo "$output"
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
run ${KPOD_BINARY} $KPOD_OPTIONS rmi debian:6.0.10 run ${KPOD_BINARY} $KPOD_OPTIONS rmi debian:6.0.10

49
test/kpod_mount.bats Normal file
View file

@ -0,0 +1,49 @@
#!/usr/bin/env bats
function teardown() {
cleanup_test
}
load helpers
IMAGE="redis:alpine"
ROOT="$TESTDIR/crio"
RUNROOT="$TESTDIR/crio-run"
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT ${STORAGE_OPTS}"
@test "mount" {
start_crio
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
echo "$output"
[ "$status" -eq 0 ]
pod_id="$output"
run crioctl image pull "$IMAGE"
echo "$output"
[ "$status" -eq 0 ]
run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id"
echo "$output"
[ "$status" -eq 0 ]
ctr_id="$output"
run ${KPOD_BINARY} ${KPOD_OPTIONS} mount $ctr_id
echo "$output"
echo ${KPOD_BINARY} ${KPOD_OPTIONS} mount $ctr_id
[ "$status" -eq 0 ]
run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} mount --notruncate | grep $ctr_id"
echo "$output"
[ "$status" -eq 0 ]
run ${KPOD_BINARY} ${KPOD_OPTIONS} unmount $ctr_id
echo "$output"
[ "$status" -eq 0 ]
run ${KPOD_BINARY} ${KPOD_OPTIONS} mount $ctr_id
echo "$output"
[ "$status" -eq 0 ]
root="$output"
run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} mount --format=json | python -m json.tool | grep $ctr_id"
echo "$output"
[ "$status" -eq 0 ]
touch $root/foobar
${KPOD_BINARY} ${KPOD_OPTIONS} unmount $ctr_id
cleanup_ctrs
cleanup_pods
stop_crio
}