summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.copr/prepare.sh17
-rwxr-xr-xAPI.md8
-rw-r--r--Makefile16
-rw-r--r--cmd/podman/cliconfig/config.go8
-rw-r--r--cmd/podman/containers_prune.go21
-rw-r--r--cmd/podman/main_local.go2
-rw-r--r--cmd/podman/reset.go71
-rw-r--r--cmd/podman/shared/container.go24
-rw-r--r--cmd/podman/system.go1
-rw-r--r--cmd/podman/system_prune.go2
-rw-r--r--cmd/podman/varlink/io.podman.varlink4
-rw-r--r--cmd/podman/version.go66
-rw-r--r--commands.md172
-rw-r--r--completions/bash/podman19
-rw-r--r--docs/source/markdown/podman-container-prune.1.md22
-rw-r--r--docs/source/markdown/podman-system-reset.1.md25
-rw-r--r--docs/source/markdown/podman-system.1.md5
-rw-r--r--docs/source/markdown/podman-version.1.md4
-rw-r--r--install.md2
-rw-r--r--libpod/boltdb_state_linux.go8
-rw-r--r--libpod/container_api.go17
-rw-r--r--libpod/container_internal.go5
-rw-r--r--libpod/container_internal_linux.go5
-rw-r--r--libpod/define/containerstate.go7
-rw-r--r--libpod/oci_util.go6
-rw-r--r--libpod/options.go84
-rw-r--r--libpod/reset.go107
-rw-r--r--libpod/runtime.go18
-rw-r--r--libpod/runtime_ctr.go55
-rw-r--r--libpod/runtime_migrate_unsupported.go4
-rw-r--r--libpod/util.go25
-rw-r--r--libpod/volume_internal.go12
-rw-r--r--pkg/adapter/containers.go31
-rw-r--r--pkg/adapter/containers_remote.go2
-rw-r--r--pkg/adapter/reset.go13
-rw-r--r--pkg/adapter/reset_remote.go12
-rw-r--r--pkg/varlinkapi/system.go22
-rw-r--r--rootless.md2
-rw-r--r--test/e2e/libpod_suite_test.go4
-rw-r--r--test/e2e/prune_test.go2
-rw-r--r--test/e2e/system_reset_test.go83
-rw-r--r--test/e2e/version_test.go16
42 files changed, 782 insertions, 247 deletions
diff --git a/.copr/prepare.sh b/.copr/prepare.sh
index d8ad34d08..713cdc2ee 100644
--- a/.copr/prepare.sh
+++ b/.copr/prepare.sh
@@ -1,12 +1,14 @@
#!/bin/sh -euf
-set -x
+set -euxo pipefail
OS_TEST=${OS_TEST:=0}
if [ ! -e /usr/bin/git ]; then
dnf -y install git-core
fi
-git fetch --unshallow || :
+if [ -f $(git rev-parse --git-dir)/shallow ]; then
+ git fetch --unshallow
+fi
COMMIT=$(git rev-parse HEAD)
COMMIT_SHORT=$(git rev-parse --short=8 HEAD)
@@ -26,7 +28,12 @@ if [ ${OS_TEST} -eq 0 ]; then
sed -i "s/${BR}/${NEWBR}/g" contrib/spec/podman.spec
fi
-mkdir build/
+mkdir -p build/
git archive --prefix "libpod-${COMMIT_SHORT}/" --format "tar.gz" HEAD -o "build/libpod-${COMMIT_SHORT}.tar.gz"
-git clone https://github.com/containers/conmon
-cd conmon && git checkout 6f3572558b97bc60dd8f8c7f0807748e6ce2c440 && git archive --prefix "conmon/" --format "tar.gz" HEAD -o "../build/conmon.tar.gz"
+if [ ! -d conmon ]; then
+ git clone -n --quiet https://github.com/containers/conmon
+fi
+pushd conmon
+git checkout 6f3572558b97bc60dd8f8c7f0807748e6ce2c440
+git archive --prefix "conmon/" --format "tar.gz" HEAD -o "../build/conmon.tar.gz"
+popd
diff --git a/API.md b/API.md
index a02a8cf6f..3a66db83b 100755
--- a/API.md
+++ b/API.md
@@ -149,6 +149,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func RemovePod(name: string, force: bool) string](#RemovePod)
+[func Reset() ](#Reset)
+
[func RestartContainer(name: string, timeout: int) string](#RestartContainer)
[func RestartPod(name: string) string](#RestartPod)
@@ -1059,6 +1061,12 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.RemovePod '{"name": "62f4
"pod": "62f4fd98cb57f529831e8f90610e54bba74bd6f02920ffb485e15376ed365c20"
}
~~~
+### <a name="Reset"></a>func Reset
+<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
+
+method Reset() </div>
+Reset resets Podman back to its initial state.
+Removes all Pods, Containers, Images and Volumes
### <a name="RestartContainer"></a>func RestartContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
diff --git a/Makefile b/Makefile
index dd948fc8e..d7c3cf7bd 100644
--- a/Makefile
+++ b/Makefile
@@ -318,7 +318,7 @@ $(MANPAGES): %: %.md .gopathok
docdir:
mkdir -p docs/build/man
-docs: docdir $(MANPAGES) ## Generate documentation
+docs: .install.md2man docdir $(MANPAGES) ## Generate documentation
install-podman-remote-%-docs: podman-remote docs $(MANPAGES)
rm -rf docs/build/remote
@@ -532,19 +532,23 @@ vendor-in-container:
.PHONY: \
.gopathok \
binaries \
+ changelog \
clean \
- validate.completions \
default \
docs \
gofmt \
+ golangci-lint \
help \
install \
- golangci-lint \
+ install.libseccomp.sudo \
lint \
pause \
- uninstall \
shell \
- changelog \
+ uninstall \
validate \
- install.libseccomp.sudo \
+ validate.completions \
vendor
+
+rpm:
+ @echo "Building rpms ..."
+ ./contrib/build_rpm.sh
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index a34afa827..c15ce8829 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -183,7 +183,8 @@ type PruneImagesValues struct {
type PruneContainersValues struct {
PodmanCommand
- Force bool
+ Force bool
+ Filter []string
}
type PodPruneValues struct {
@@ -658,6 +659,11 @@ type SystemPruneValues struct {
Volume bool
}
+type SystemResetValues struct {
+ PodmanCommand
+ Force bool
+}
+
type SystemRenumberValues struct {
PodmanCommand
}
diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go
index 3d0fef37d..78c50268c 100644
--- a/cmd/podman/containers_prune.go
+++ b/cmd/podman/containers_prune.go
@@ -1,6 +1,11 @@
package main
import (
+ "bufio"
+ "fmt"
+ "os"
+ "strings"
+
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/define"
@@ -36,9 +41,23 @@ func init() {
pruneContainersCommand.SetUsageTemplate(UsageTemplate())
flags := pruneContainersCommand.Flags()
flags.BoolVarP(&pruneContainersCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
+ flags.StringArrayVar(&pruneContainersCommand.Filter, "filter", []string{}, "Provide filter values (e.g. 'until=<timestamp>')")
}
func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
+ if !c.Force {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Printf(`WARNING! This will remove all stopped containers.
+Are you sure you want to continue? [y/N] `)
+ ans, err := reader.ReadString('\n')
+ if err != nil {
+ return errors.Wrapf(err, "error reading input")
+ }
+ if strings.ToLower(ans)[0] != 'y' {
+ return nil
+ }
+ }
+
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
@@ -49,7 +68,7 @@ func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalFlags.MaxWorks
}
- ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force)
+ ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force, c.Filter)
if err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr {
if len(c.InputArgs) > 1 {
diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go
index 968d7331a..bc46e4652 100644
--- a/cmd/podman/main_local.go
+++ b/cmd/podman/main_local.go
@@ -159,7 +159,7 @@ func setupRootless(cmd *cobra.Command, args []string) error {
Remote: remoteclient,
}
- runtime, err := libpodruntime.GetRuntime(getContext(), &podmanCmd)
+ runtime, err := libpodruntime.GetRuntimeNoStore(getContext(), &podmanCmd)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
diff --git a/cmd/podman/reset.go b/cmd/podman/reset.go
new file mode 100644
index 000000000..9d16dc978
--- /dev/null
+++ b/cmd/podman/reset.go
@@ -0,0 +1,71 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ systemResetCommand cliconfig.SystemResetValues
+ systemResetDescription = `Reset podman storage back to default state"
+
+ All containers will be stopped and removed, and all images, volumes and container content will be removed.
+`
+ _systemResetCommand = &cobra.Command{
+ Use: "reset",
+ Args: noSubArgs,
+ Short: "Reset podman storage",
+ Long: systemResetDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ systemResetCommand.InputArgs = args
+ systemResetCommand.GlobalFlags = MainGlobalOpts
+ systemResetCommand.Remote = remoteclient
+ return systemResetCmd(&systemResetCommand)
+ },
+ }
+)
+
+func init() {
+ systemResetCommand.Command = _systemResetCommand
+ flags := systemResetCommand.Flags()
+ flags.BoolVarP(&systemResetCommand.Force, "force", "f", false, "Do not prompt for confirmation")
+
+ systemResetCommand.SetHelpTemplate(HelpTemplate())
+ systemResetCommand.SetUsageTemplate(UsageTemplate())
+}
+
+func systemResetCmd(c *cliconfig.SystemResetValues) error {
+ // Prompt for confirmation if --force is not set
+ if !c.Force {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Print(`
+WARNING! This will remove:
+ - all containers
+ - all pods
+ - all images
+ - all build cache
+Are you sure you want to continue? [y/N] `)
+ ans, err := reader.ReadString('\n')
+ if err != nil {
+ return errors.Wrapf(err, "error reading input")
+ }
+ if strings.ToLower(ans)[0] != 'y' {
+ return nil
+ }
+ }
+
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "error creating libpod runtime")
+ }
+ // No shutdown, since storage will be destroyed when command completes
+
+ return runtime.Reset()
+}
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index f49943477..4f2002992 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/timetype"
"github.com/containers/libpod/pkg/util"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-units"
@@ -195,6 +196,8 @@ func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput
status = "Paused"
case define.ContainerStateCreated.String(), define.ContainerStateConfigured.String():
status = "Created"
+ case define.ContainerStateRemoving.String():
+ status = "Removing"
default:
status = "Error"
}
@@ -272,7 +275,8 @@ func worker(wg *sync.WaitGroup, jobs <-chan workerInput, results chan<- PsContai
}
}
-func generateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
+// GenerateContainerFilterFuncs return ContainerFilter functions based of filter.
+func GenerateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
switch filter {
case "id":
return func(c *libpod.Container) bool {
@@ -394,6 +398,22 @@ func generateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime)
}
return hcStatus == filterValue
}, nil
+ case "until":
+ ts, err := timetype.GetTimestamp(filterValue, time.Now())
+ if err != nil {
+ return nil, err
+ }
+ seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
+ if err != nil {
+ return nil, err
+ }
+ until := time.Unix(seconds, nanoseconds)
+ return func(c *libpod.Container) bool {
+ if !until.IsZero() && c.CreatedTime().After((until)) {
+ return true
+ }
+ return false
+ }, nil
}
return nil, errors.Errorf("%s is an invalid filter", filter)
}
@@ -411,7 +431,7 @@ func GetPsContainerOutput(r *libpod.Runtime, opts PsOptions, filters []string, m
if len(filterSplit) < 2 {
return nil, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
}
- generatedFunc, err := generateContainerFilterFuncs(filterSplit[0], filterSplit[1], r)
+ generatedFunc, err := GenerateContainerFilterFuncs(filterSplit[0], filterSplit[1], r)
if err != nil {
return nil, errors.Wrapf(err, "invalid filter")
}
diff --git a/cmd/podman/system.go b/cmd/podman/system.go
index 80080bf44..921d0c037 100644
--- a/cmd/podman/system.go
+++ b/cmd/podman/system.go
@@ -19,6 +19,7 @@ var (
)
var systemCommands = []*cobra.Command{
+ _systemResetCommand,
_infoCommand,
_pruneSystemCommand,
}
diff --git a/cmd/podman/system_prune.go b/cmd/podman/system_prune.go
index ae5d7ed2d..74fdcde99 100644
--- a/cmd/podman/system_prune.go
+++ b/cmd/podman/system_prune.go
@@ -92,7 +92,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
rmWorkers := shared.Parallelize("rm")
fmt.Println("Deleted Containers")
- ok, failures, err = runtime.Prune(ctx, rmWorkers, false)
+ ok, failures, err = runtime.Prune(ctx, rmWorkers, false, []string{})
if err != nil {
if lasterr != nil {
logrus.Errorf("%q", err)
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index e76b9627e..a3fd27ed6 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -536,6 +536,10 @@ method GetVersion() -> (
remote_api_version: int
)
+# Reset resets Podman back to its initial state.
+# Removes all Pods, Containers, Images and Volumes
+method Reset() -> ()
+
# GetInfo returns a [PodmanInfo](#PodmanInfo) struct that describes podman and its host such as storage stats,
# build information of Podman, and system-wide registries.
method GetInfo() -> (info: PodmanInfo)
diff --git a/cmd/podman/version.go b/cmd/podman/version.go
index 314b2e266..5907241ff 100644
--- a/cmd/podman/version.go
+++ b/cmd/podman/version.go
@@ -37,13 +37,40 @@ func init() {
flags := versionCommand.Flags()
flags.StringVarP(&versionCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
}
+func getRemoteVersion(c *cliconfig.VersionValues) (version define.Version, err error) {
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return version, errors.Wrapf(err, "could not get runtime")
+ }
+ defer runtime.DeferredShutdown(false)
+
+ return runtime.GetVersion()
+}
+
+type versionStruct struct {
+ Client define.Version
+ Server define.Version
+}
// versionCmd gets and prints version info for version command
func versionCmd(c *cliconfig.VersionValues) error {
- clientVersion, err := define.GetVersion()
+
+ var (
+ v versionStruct
+ err error
+ )
+ v.Client, err = define.GetVersion()
if err != nil {
return errors.Wrapf(err, "unable to determine version")
}
+ if remote {
+ v.Server, err = getRemoteVersion(c)
+ if err != nil {
+ return err
+ }
+ } else {
+ v.Server = v.Client
+ }
versionOutputFormat := c.Format
if versionOutputFormat != "" {
@@ -53,11 +80,20 @@ func versionCmd(c *cliconfig.VersionValues) error {
var out formats.Writer
switch versionOutputFormat {
case formats.JSONString:
- out = formats.JSONStruct{Output: clientVersion}
+ out = formats.JSONStruct{Output: v}
+ return out.Out()
default:
- out = formats.StdoutTemplate{Output: clientVersion, Template: versionOutputFormat}
+ out = formats.StdoutTemplate{Output: v, Template: versionOutputFormat}
+ err := out.Out()
+ if err != nil {
+ // On Failure, assume user is using older version of podman version --format and check client
+ out = formats.StdoutTemplate{Output: v.Client, Template: versionOutputFormat}
+ if err1 := out.Out(); err1 != nil {
+ return err
+ }
+ }
}
- return out.Out()
+ return nil
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
defer w.Flush()
@@ -66,25 +102,13 @@ func versionCmd(c *cliconfig.VersionValues) error {
if _, err := fmt.Fprintf(w, "Client:\n"); err != nil {
return err
}
- }
- formatVersion(w, clientVersion)
-
- if remote {
- if _, err := fmt.Fprintf(w, "\nService:\n"); err != nil {
- return err
- }
-
- runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
- if err != nil {
- return errors.Wrapf(err, "could not get runtime")
- }
- defer runtime.DeferredShutdown(false)
-
- serviceVersion, err := runtime.GetVersion()
- if err != nil {
+ formatVersion(w, v.Client)
+ if _, err := fmt.Fprintf(w, "\nServer:\n"); err != nil {
return err
}
- formatVersion(w, serviceVersion)
+ formatVersion(w, v.Server)
+ } else {
+ formatVersion(w, v.Client)
}
return nil
}
diff --git a/commands.md b/commands.md
index c035b011f..de9169a4b 100644
--- a/commands.md
+++ b/commands.md
@@ -6,89 +6,95 @@
| Command | Description | Demo | Script |
| :----------------------------------------------------------------------- | :------------------------------------------------------------------------- | :-------------------------------------------------------------------------- | :---------------------------------------------------------------------------------- |
-| [podman(1)](/docs/podman.1.md) | Simple management tool for pods and images |
-| [podman-attach(1)](/docs/podman-attach.1.md) | Attach to a running container |
-| [podman-build(1)](/docs/podman-build.1.md) | Build an image using instructions from Dockerfiles |
-| [podman-commit(1)](/docs/podman-commit.1.md) | Create new image based on the changed container |
-| [podman-container(1)](/docs/podman-container.1.md) | Manage Containers |
-| [podman-container-checkpoint(1)](/docs/podman-container-checkpoint.1.md) | Checkpoints one or more running containers |
-| [podman-container-cleanup(1)](/docs/podman-container-cleanup.1.md) | Cleanup Container storage and networks |
-| [podman-container-exists(1)](/docs/podman-container-exists.1.md) | Check if an container exists in local storage |
-| [podman-container-prune(1)](/docs/podman-container-prune.1.md) | Remove all stopped containers |
-| [podman-container-refresh(1)](/docs/podman-container-refresh.1.md) | Refresh all containers state in database |
-| [podman-container-restore(1)](/docs/podman-container-restore.1.md) | Restores one or more running containers |
-| [podman-container-runlabel(1)](/docs/podman-container-runlabel.1.md) | Execute Image Label Method |
-| [podman-cp(1)](/docs/podman-cp.1.md) | Copy files/folders between a container and the local filesystem |
-| [podman-create(1)](/docs/podman-create.1.md) | Create a new container |
-| [podman-diff(1)](/docs/podman-diff.1.md) | Inspect changes on a container or image's filesystem |
-| [podman-events(1)](/docs/podman-events.1.md) | Monitor Podman events |
-| [podman-exec(1)](/docs/podman-exec.1.md) | Execute a command in a running container |
-| [podman-export(1)](/docs/podman-export.1.md) | Export container's filesystem contents as a tar archive |
-| [podman-generate(1)](/docs/podman-generate.1.md) | Generate structured output based on Podman containers and pods |
-| [podman-generate-kube(1)](/docs/podman-generate-kube.1.md) | Generate Kubernetes YAML based on a container or Pod |
-| [podman-generate-systemd(1)](/docs/podman-generate-systemd.1.md) | Generate a Systemd unit file for a container |
-| [podman-history(1)](/docs/podman-history.1.md) | Shows the history of an image |
-| [podman-image(1)](/docs/podman-image.1.md) | Manage Images |
-| [podman-image-exists(1)](/docs/podman-image-exists.1.md) | Check if an image exists in local storage |
-| [podman-image-prune(1)](/docs/podman-image-prune.1.md) | Remove all unused images |
-| [podman-image-sign(1)](/docs/podman-image-sign.1.md) | Create a signature for an image |
-| [podman-image-trust(1)](/docs/podman-image-trust.1.md) | Manage container registry image trust policy |
-| [podman-images(1)](/docs/podman-images.1.md) | List images in local storage | [![...](/docs/play.png)](https://podman.io/asciinema/podman/images/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_images.sh) |
-| [podman-import(1)](/docs/podman-import.1.md) | Import a tarball and save it as a filesystem image |
-| [podman-info(1)](/docs/podman-info.1.md) | Display system information |
-| [podman-init(1)](/docs/podman-init.1.md) | Initialize a container |
-| [podman-inspect(1)](/docs/podman-inspect.1.md) | Display the configuration of a container or image | [![...](/docs/play.png)](https://asciinema.org/a/133418) |
-| [podman-kill(1)](/docs/podman-kill.1.md) | Kill the main process in one or more running containers |
-| [podman-load(1)](/docs/podman-load.1.md) | Load an image from a container image archive |
-| [podman-login(1)](/docs/podman-login.1.md) | Login to a container registry |
-| [podman-logout(1)](/docs/podman-logout.1.md) | Logout of a container registry |
-| [podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |
-| [podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |
-| [podman-network(1)](/docs/podman-network.1.md) | Manage Podman CNI networks |
-| [podman-network-create(1)](/docs/podman-network-create.1.md) | Create a CNI network |
-| [podman-network-inspect(1)](/docs/podman-network-inspect.1.md) | Inspect one or more Podman networks |
-| [podman-network-ls(1)](/docs/podman-network-ls.1.md) | Display a summary of Podman networks |
-| [podman-network-rm(1)](/docs/podman-network-rm.1.md) | Remove one or more Podman networks |
-| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers | [![...](/docs/play.png)](https://podman.io/asciinema/podman/pause_unpause/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_pause_unpause.sh) |
-| [podman-play(1)](/docs/podman-play.1.md) | Play pods and containers based on a structured input file |
-| [podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
-| [podman-pod-create(1)](/docs/podman-pod-create.1.md) | Create a new pod |
-| [podman-pod-inspect(1)](/docs/podman-pod-inspect.1.md) | Inspect a pod |
+| [podman(1)](/docs/source/markdown/podman.1.md) | Simple management tool for pods and images |
+| [podman-attach(1)](/docs/source/markdown/podman-attach.1.md) | Attach to a running container |
+| [podman-build(1)](/docs/source/markdown/podman-build.1.md) | Build an image using instructions from Dockerfiles |
+| [podman-commit(1)](/docs/source/markdown/podman-commit.1.md) | Create new image based on the changed container |
+| [podman-container(1)](/docs/source/markdown/podman-container.1.md) | Manage Containers |
+| [podman-container-checkpoint(1)](/docs/source/markdown/podman-container-checkpoint.1.md) | Checkpoints one or more running containers |
+| [podman-container-cleanup(1)](/docs/source/markdown/podman-container-cleanup.1.md) | Cleanup Container storage and networks |
+| [podman-container-exists(1)](/docs/source/markdown/podman-container-exists.1.md) | Check if an container exists in local storage |
+| [podman-container-prune(1)](/docs/source/markdown/podman-container-prune.1.md) | Remove all stopped containers |
+| [podman-container-refresh(1)](/docs/source/markdown/podman-container-refresh.1.md) | Refresh all containers state in database |
+| [podman-container-restore(1)](/docs/source/markdown/podman-container-restore.1.md) | Restores one or more running containers |
+| [podman-container-runlabel(1)](/docs/source/markdown/podman-container-runlabel.1.md) | Execute Image Label Method |
+| [podman-cp(1)](/docs/source/markdown/podman-cp.1.md) | Copy files/folders between a container and the local filesystem |
+| [podman-create(1)](/docs/source/markdown/podman-create.1.md) | Create a new container |
+| [podman-diff(1)](/docs/source/markdown/podman-diff.1.md) | Inspect changes on a container or image's filesystem |
+| [podman-events(1)](/docs/source/markdown/podman-events.1.md) | Monitor Podman events |
+| [podman-exec(1)](/docs/source/markdown/podman-exec.1.md) | Execute a command in a running container |
+| [podman-export(1)](/docs/source/markdown/podman-export.1.md) | Export container's filesystem contents as a tar archive |
+| [podman-generate(1)](/docs/source/markdown/podman-generate.1.md) | Generate structured output based on Podman containers and pods |
+| [podman-generate-kube(1)](/docs/source/markdown/podman-generate-kube.1.md) | Generate Kubernetes YAML based on a container or Pod |
+| [podman-generate-systemd(1)](/docs/source/markdown/podman-generate-systemd.1.md) | Generate a Systemd unit file for a container |
+| [podman-history(1)](/docs/source/markdown/podman-history.1.md) | Shows the history of an image |
+| [podman-image(1)](/docs/source/markdown/podman-image.1.md) | Manage Images |
+| [podman-image-exists(1)](/docs/source/markdown/podman-image-exists.1.md) | Check if an image exists in local storage |
+| [podman-image-prune(1)](/docs/source/markdown/podman-image-prune.1.md) | Remove all unused images |
+| [podman-image-sign(1)](/docs/source/markdown/podman-image-sign.1.md) | Create a signature for an image |
+| [podman-image-trust(1)](/docs/source/markdown/podman-image-trust.1.md) | Manage container registry image trust policy |
+| [podman-images(1)](/docs/source/markdown/podman-images.1.md) | List images in local storage | [![...](/docs/source/markdown/play.png)](https://podman.io/asciinema/podman/images/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_images.sh) |
+| [podman-import(1)](/docs/source/markdown/podman-import.1.md) | Import a tarball and save it as a filesystem image |
+| [podman-info(1)](/docs/source/markdown/podman-info.1.md) | Display system information |
+| [podman-init(1)](/docs/source/markdown/podman-init.1.md) | Initialize a container |
+| [podman-inspect(1)](/docs/source/markdown/podman-inspect.1.md) | Display the configuration of a container or image | [![...](/docs/source/markdown/play.png)](https://asciinema.org/a/133418) |
+| [podman-kill(1)](/docs/source/markdown/podman-kill.1.md) | Kill the main process in one or more running containers |
+| [podman-load(1)](/docs/source/markdown/podman-load.1.md) | Load an image from a container image archive |
+| [podman-login(1)](/docs/source/markdown/podman-login.1.md) | Login to a container registry |
+| [podman-logout(1)](/docs/source/markdown/podman-logout.1.md) | Logout of a container registry |
+| [podman-logs(1)](/docs/source/markdown/podman-logs.1.md) | Display the logs of a container |
+| [podman-mount(1)](/docs/source/markdown/podman-mount.1.md) | Mount a working container's root filesystem |
+| [podman-network(1)](/docs/source/markdown/podman-network.1.md) | Manage Podman CNI networks |
+| [podman-network-create(1)](/docs/source/markdown/podman-network-create.1.md) | Create a CNI network |
+| [podman-network-inspect(1)](/docs/source/markdown/podman-network-inspect.1.md) | Inspect one or more Podman networks |
+| [podman-network-ls(1)](/docs/source/markdown/podman-network-ls.1.md) | Display a summary of Podman networks |
+| [podman-network-rm(1)](/docs/source/markdown/podman-network-rm.1.md) | Remove one or more Podman networks |
+| [podman-pause(1)](/docs/source/markdown/podman-pause.1.md) | Pause one or more running containers | [![...](/docs/source/markdown/play.png)](https://podman.io/asciinema/podman/pause_unpause/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_pause_unpause.sh) |
+| [podman-play(1)](/docs/source/markdown/podman-play.1.md) | Play pods and containers based on a structured input file |
+| [podman-pod(1)](/docs/source/markdown/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
+| [podman-pod-create(1)](/docs/source/markdown/podman-pod-create.1.md) | Create a new pod |
+| [podman-pod-inspect(1)](/docs/source/markdown/podman-pod-inspect.1.md) | Inspect a pod |
| [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. |
-| [podman-pod-ps(1)](/docs/podman-pod-ps.1.md) | List the pods on the system |
+| [podman-pod-ps(1)](/docs/source/markdown/podman-pod-ps.1.md) | List the pods on the system |
| [podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. |
-| [podman-pod-restart](/docs/podman-pod-restart.1.md) | Restart one or more pods |
-| [podman-pod-rm(1)](/docs/podman-pod-rm.1.md) | Remove one or more pods |
-| [podman-pod-start(1)](/docs/podman-pod-start.1.md) | Start one or more pods |
-| [podman-pod-stats(1)](/docs/podman-pod-stats.1.md) | Display a live stream of one or more pods' resource usage statistics | | |
-| [podman-pod-stop(1)](/docs/podman-pod-stop.1.md) | Stop one or more pods |
-| [podman-pod-top(1)](/docs/podman-pod-top.1.md) | Display the running processes of a pod |
+| [podman-pod-restart](/docs/source/markdown/podman-pod-restart.1.md) | Restart one or more pods |
+| [podman-pod-rm(1)](/docs/source/markdown/podman-pod-rm.1.md) | Remove one or more pods |
+| [podman-pod-start(1)](/docs/source/markdown/podman-pod-start.1.md) | Start one or more pods |
+| [podman-pod-stats(1)](/docs/source/markdown/podman-pod-stats.1.md) | Display a live stream of one or more pods' resource usage statistics | | |
+| [podman-pod-stop(1)](/docs/source/markdown/podman-pod-stop.1.md) | Stop one or more pods |
+| [podman-pod-top(1)](/docs/source/markdown/podman-pod-top.1.md) | Display the running processes of a pod |
| [podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. |
-| [podman-port(1)](/docs/podman-port.1.md) | List port mappings for running containers |
-| [podman-ps(1)](/docs/podman-ps.1.md) | Prints out information about containers |
-| [podman-pull(1)](/docs/podman-pull.1.md) | Pull an image from a registry |
-| [podman-push(1)](/docs/podman-push.1.md) | Push an image to a specified destination | [![...](/docs/play.png)](https://asciinema.org/a/133276) |
-| [podman-restart](/docs/podman-restart.1.md) | Restarts one or more containers | [![...](/docs/play.png)](https://asciinema.org/a/jiqxJAxcVXw604xdzMLTkQvHM) |
-| [podman-rm(1)](/docs/podman-rm.1.md) | Removes one or more containers |
-| [podman-rmi(1)](/docs/podman-rmi.1.md) | Removes one or more images |
-| [podman-run(1)](/docs/podman-run.1.md) | Run a command in a container |
-| [podman-save(1)](/docs/podman-save.1.md) | Saves an image to an archive |
-| [podman-search(1)](/docs/podman-search.1.md) | Search a registry for an image |
-| [podman-start(1)](/docs/podman-start.1.md) | Starts one or more containers |
-| [podman-stats(1)](/docs/podman-stats.1.md) | Display a live stream of one or more containers' resource usage statistics |
-| [podman-stop(1)](/docs/podman-stop.1.md) | Stops one or more running containers |
-| [podman-system(1)](/docs/podman-system.1.md) | Manage podman |
-| [podman-tag(1)](/docs/podman-tag.1.md) | Add an additional name to a local image | [![...](/docs/play.png)](https://asciinema.org/a/133803) |
-| [podman-top(1)](/docs/podman-top.1.md) | Display the running processes of a container |
-| [podman-umount(1)](/docs/podman-umount.1.md) | Unmount a working container's root filesystem |
-| [podman-unpause(1)](/docs/podman-unpause.1.md) | Unpause one or more running containers | [![...](/docs/play.png)](https://podman.io/asciinema/podman/pause_unpause/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_pause_unpause.sh) |
-| [podman-unshare(1)](/docs/podman-unshare.1.md) | Run a command inside of a modified user namespace. |
-| [podman-varlink(1)](/docs/podman-varlink.1.md) | Run the varlink backend |
-| [podman-version(1)](/docs/podman-version.1.md) | Display the version information |
-| [podman-volume(1)](/docs/podman-volume.1.md) | Manage Volumes |
-| [podman-volume-create(1)](/docs/podman-volume-create.1.md) | Create a volume |
-| [podman-volume-inspect(1)](/docs/podman-volume-inspect.1.md) | Get detailed information on one or more volumes |
-| [podman-volume-ls(1)](/docs/podman-volume-ls.1.md) | List all the available volumes |
-| [podman-volume-rm(1)](/docs/podman-volume-rm.1.md) | Remove one or more volumes |
-| [podman-volume-prune(1)](/docs/podman-volume-prune.1.md) | Remove all unused volumes |
-| [podman-wait(1)](/docs/podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes |
+| [podman-port(1)](/docs/source/markdown/podman-port.1.md) | List port mappings for running containers |
+| [podman-ps(1)](/docs/source/markdown/podman-ps.1.md) | Prints out information about containers |
+| [podman-pull(1)](/docs/source/markdown/podman-pull.1.md) | Pull an image from a registry |
+| [podman-push(1)](/docs/source/markdown/podman-push.1.md) | Push an image to a specified destination | [![...](/docs/source/markdown/play.png)](https://asciinema.org/a/133276) |
+| [podman-restart](/docs/source/markdown/podman-restart.1.md) | Restarts one or more containers | [![...](/docs/source/markdown/play.png)](https://asciinema.org/a/jiqxJAxcVXw604xdzMLTkQvHM) |
+| [podman-rm(1)](/docs/source/markdown/podman-rm.1.md) | Removes one or more containers |
+| [podman-rmi(1)](/docs/source/markdown/podman-rmi.1.md) | Removes one or more images |
+| [podman-run(1)](/docs/source/markdown/podman-run.1.md) | Run a command in a container |
+| [podman-save(1)](/docs/source/markdown/podman-save.1.md) | Saves an image to an archive |
+| [podman-search(1)](/docs/source/markdown/podman-search.1.md) | Search a registry for an image |
+| [podman-start(1)](/docs/source/markdown/podman-start.1.md) | Starts one or more containers |
+| [podman-stats(1)](/docs/source/markdown/podman-stats.1.md) | Display a live stream of one or more containers' resource usage statistics |
+| [podman-stop(1)](/docs/source/markdown/podman-stop.1.md) | Stops one or more running containers |
+| [podman-system(1)](/docs/source/markdown/podman-system.1.md) | Manage podman |
+| [podman-system-df(1)](/docs/source/markdown/podman-system-df.1.md) | Show podman disk usage. |
+| [podman-system-info(1)](/docs/source/markdown/podman-info.1.md) | Displays Podman related system information. |
+| [podman-system-migrate(1)](/docs/source/markdown/podman-system-migrate.1.md) | Migrate existing containers to a new podman version. |
+| [podman-system-prune(1)](/docs/source/markdown/podman-system-prune.1.md) | Remove all unused container, image and volume data. |
+| [podman-system-renumber(1)](/docs/source/markdown/podman-system-renumber.1.md) | Migrate lock numbers to handle a change in maximum number of locks. |
+| [podman-system-reset(1)](/docs/source/markdown/podman-system-reset.1.md) | Reset storage back to original state. Remove all pods, containers, images, volumes. |
+| [podman-tag(1)](/docs/source/markdown/podman-tag.1.md) | Add an additional name to a local image | [![...](/docs/source/markdown/play.png)](https://asciinema.org/a/133803) |
+| [podman-top(1)](/docs/source/markdown/podman-top.1.md) | Display the running processes of a container |
+| [podman-umount(1)](/docs/source/markdown/podman-umount.1.md) | Unmount a working container's root filesystem |
+| [podman-unpause(1)](/docs/source/markdown/podman-unpause.1.md) | Unpause one or more running containers | [![...](/docs/source/markdown/play.png)](https://podman.io/asciinema/podman/pause_unpause/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_pause_unpause.sh) |
+| [podman-unshare(1)](/docs/source/markdown/podman-unshare.1.md) | Run a command inside of a modified user namespace. |
+| [podman-varlink(1)](/docs/source/markdown/podman-varlink.1.md) | Run the varlink backend |
+| [podman-version(1)](/docs/source/markdown/podman-version.1.md) | Display the version information |
+| [podman-volume(1)](/docs/source/markdown/podman-volume.1.md) | Manage Volumes |
+| [podman-volume-create(1)](/docs/source/markdown/podman-volume-create.1.md) | Create a volume |
+| [podman-volume-inspect(1)](/docs/source/markdown/podman-volume-inspect.1.md) | Get detailed information on one or more volumes |
+| [podman-volume-ls(1)](/docs/source/markdown/podman-volume-ls.1.md) | List all the available volumes |
+| [podman-volume-rm(1)](/docs/source/markdown/podman-volume-rm.1.md) | Remove one or more volumes |
+| [podman-volume-prune(1)](/docs/source/markdown/podman-volume-prune.1.md) | Remove all unused volumes |
+| [podman-wait(1)](/docs/source/markdown/podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes |
diff --git a/completions/bash/podman b/completions/bash/podman
index 6d145030f..18e2460ec 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -1142,6 +1142,21 @@ _podman_container() {
esac
}
+_podman_system_reset() {
+ local options_with_args="
+ "
+ local boolean_options="
+ -h
+ --help
+ --force
+ "
+ case "$cur" in
+ -*)
+ COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
+ ;;
+ esac
+}
+
_podman_system_df() {
local options_with_args="
--format
@@ -1193,6 +1208,7 @@ _podman_system() {
df
info
prune
+ reset
"
__podman_subcommands "$subcommands" && return
@@ -2816,9 +2832,12 @@ _podman_images_prune() {
_podman_container_prune() {
local options_with_args="
+ --filter
"
local boolean_options="
+ -f
+ --force
-h
--help
"
diff --git a/docs/source/markdown/podman-container-prune.1.md b/docs/source/markdown/podman-container-prune.1.md
index d8a4b7f4e..856843a80 100644
--- a/docs/source/markdown/podman-container-prune.1.md
+++ b/docs/source/markdown/podman-container-prune.1.md
@@ -20,6 +20,8 @@ Print usage statement
Remove all stopped containers from local storage
```
$ sudo podman container prune
+WARNING! This will remove all stopped containers.
+Are you sure you want to continue? [y/N] y
878392adf2e6c5c9bb1fc19b69d37d2e98c8abf9d539c0bce4b15b46bbcce471
37664467fbe3618bf9479c34393ac29c02696675addf1750f9e346581636cde7
ed0c6468b8e1cb641b4621d1fe30cb477e1fefc5c0bceb66feaf2f7cb50e5962
@@ -28,6 +30,26 @@ fff1c5b6c3631746055ec40598ce8ecaa4b82aef122f9e3a85b03b55c0d06c23
602d343cd47e7cb3dfc808282a9900a3e4555747787ec6723bb68cedab8384d5
```
+Remove all stopped containers from local storage without confirmation.
+```
+$ sudo podman container prune -f
+878392adf2e6c5c9bb1fc19b69d37d2e98c8abf9d539c0bce4b15b46bbcce471
+37664467fbe3618bf9479c34393ac29c02696675addf1750f9e346581636cde7
+ed0c6468b8e1cb641b4621d1fe30cb477e1fefc5c0bceb66feaf2f7cb50e5962
+6ac6c8f0067b7a4682e6b8e18902665b57d1a0e07e885d9abcd382232a543ccd
+fff1c5b6c3631746055ec40598ce8ecaa4b82aef122f9e3a85b03b55c0d06c23
+602d343cd47e7cb3dfc808282a9900a3e4555747787ec6723bb68cedab8384d5
+
+```
+
+Remove all stopped containers from local storage created within last 10 minutes
+```
+$ sudo podman container prune --filter until="10m"
+WARNING! This will remove all stopped containers.
+Are you sure you want to continue? [y/N] y
+3d366295e33d8cc612c4d873199bacadd55088d90d17dcafaa9a2d317ad50b4e
+```
+
## SEE ALSO
podman(1), podman-ps
diff --git a/docs/source/markdown/podman-system-reset.1.md b/docs/source/markdown/podman-system-reset.1.md
new file mode 100644
index 000000000..432f275f4
--- /dev/null
+++ b/docs/source/markdown/podman-system-reset.1.md
@@ -0,0 +1,25 @@
+% podman-system-reset(1)
+
+## NAME
+podman\-system\-reset - Reset storage back to initial state
+
+## SYNOPSIS
+**podman system reset**
+
+## DESCRIPTION
+**podman system reset** removes all pods, containers, images and volumes.
+
+## OPTIONS
+**--force**, **-f**
+
+Do not prompt for confirmation
+
+**--help**, **-h**
+
+Print usage statement
+
+## SEE ALSO
+`podman(1)`, `podman-system(1)`
+
+## HISTORY
+November 2019, Originally compiled by Dan Walsh (dwalsh at redhat dot com)
diff --git a/docs/source/markdown/podman-system.1.md b/docs/source/markdown/podman-system.1.md
index bbd541066..1af97290d 100644
--- a/docs/source/markdown/podman-system.1.md
+++ b/docs/source/markdown/podman-system.1.md
@@ -15,9 +15,10 @@ The system command allows you to manage the podman systems
| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
| df | [podman-system-df(1)](podman-system-df.1.md) | Show podman disk usage. |
| 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 container, image and volume 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. |
+| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused container, image and volume data. |
+| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md)| Migrate lock numbers to handle a change in maximum number of locks. |
+| reset | [podman-system-reset(1)](podman-system-reset.1.md) | Reset storage back to initial state. |
## SEE ALSO
podman(1)
diff --git a/docs/source/markdown/podman-version.1.md b/docs/source/markdown/podman-version.1.md
index 4499f6338..de22c4800 100644
--- a/docs/source/markdown/podman-version.1.md
+++ b/docs/source/markdown/podman-version.1.md
@@ -34,8 +34,8 @@ OS/Arch: linux/amd64
Filtering out only the version:
```
-$ podman version --format '{{.Version}}'
-0.11.2
+$ podman version --format '{{.Client.Version}}'
+1.6.3
```
## SEE ALSO
diff --git a/install.md b/install.md
index 39b639176..bd3732083 100644
--- a/install.md
+++ b/install.md
@@ -68,7 +68,7 @@ The latest builds are available in a PPA. Take note of the [Build and Run Depend
```bash
sudo apt-get update -qq
-sudo apt-get install -qq -y software-properties-common uidmap
+sudo apt-get install -qq -y software-properties-common uidmap slirp4netns
sudo add-apt-repository -y ppa:projectatomic/ppa
sudo apt-get update -qq
sudo apt-get -qq -y install podman
diff --git a/libpod/boltdb_state_linux.go b/libpod/boltdb_state_linux.go
index 09a9be606..6ccda71bd 100644
--- a/libpod/boltdb_state_linux.go
+++ b/libpod/boltdb_state_linux.go
@@ -3,6 +3,8 @@
package libpod
import (
+ "github.com/containers/libpod/libpod/define"
+ "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -25,8 +27,12 @@ func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) er
if err == nil {
newState.NetNS = ns
} else {
+ if ctr.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) {
+ return errors.Wrapf(err, "error joning network namespace of container %s", ctr.ID())
+ }
+
logrus.Errorf("error joining network namespace for container %s: %v", ctr.ID(), err)
- ctr.valid = false
+ ctr.state.NetNS = nil
}
}
} else {
diff --git a/libpod/container_api.go b/libpod/container_api.go
index b8cfe02f6..153a1d628 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -404,6 +404,11 @@ func (c *Container) Mount() (string, error) {
return "", err
}
}
+
+ if c.state.State == define.ContainerStateRemoving {
+ return "", errors.Wrapf(define.ErrCtrStateInvalid, "cannot mount container %s as it is being removed", c.ID())
+ }
+
defer c.newContainerEvent(events.Mount)
return c.mount()
}
@@ -488,7 +493,12 @@ func (c *Container) Export(path string) error {
return err
}
}
- defer c.newContainerEvent(events.Export)
+
+ if c.state.State == define.ContainerStateRemoving {
+ return errors.Wrapf(define.ErrCtrStateInvalid, "cannot mount container %s as it is being removed", c.ID())
+ }
+
+ defer c.newContainerEvent(events.Mount)
return c.export(path)
}
@@ -674,6 +684,10 @@ func (c *Container) Refresh(ctx context.Context) error {
}
}
+ if c.state.State == define.ContainerStateRemoving {
+ return errors.Wrapf(define.ErrCtrStateInvalid, "cannot refresh containers that are being removed")
+ }
+
wasCreated := false
if c.state.State == define.ContainerStateCreated {
wasCreated = true
@@ -819,7 +833,6 @@ func (c *Container) Checkpoint(ctx context.Context, options ContainerCheckpointO
return err
}
}
- defer c.newContainerEvent(events.Checkpoint)
return c.checkpoint(ctx, options)
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 4ff1913b5..1e8a8a580 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -719,7 +719,8 @@ func (c *Container) isStopped() (bool, error) {
if err != nil {
return true, err
}
- return c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused, nil
+
+ return !c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused), nil
}
// save container state to the database
@@ -1057,6 +1058,8 @@ func (c *Container) initAndStart(ctx context.Context) (err error) {
// If we are ContainerStateUnknown, throw an error
if c.state.State == define.ContainerStateUnknown {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is in an unknown state", c.ID())
+ } else if c.state.State == define.ContainerStateRemoving {
+ return errors.Wrapf(define.ErrCtrStateInvalid, "cannot start container %s as it is being removed", c.ID())
}
// If we are running, do nothing
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index f051f40e9..586de0776 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -21,6 +21,7 @@ import (
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/buildah/pkg/secrets"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/annotations"
"github.com/containers/libpod/pkg/apparmor"
"github.com/containers/libpod/pkg/cgroups"
@@ -699,6 +700,8 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
return err
}
+ defer c.newContainerEvent(events.Checkpoint)
+
if options.TargetFile != "" {
if err = c.exportCheckpoint(options.TargetFile, options.IgnoreRootfs); err != nil {
return err
@@ -770,7 +773,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return err
}
- if (c.state.State != define.ContainerStateConfigured) && (c.state.State != define.ContainerStateExited) {
+ if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID())
}
diff --git a/libpod/define/containerstate.go b/libpod/define/containerstate.go
index ab2527b3e..e7d258e21 100644
--- a/libpod/define/containerstate.go
+++ b/libpod/define/containerstate.go
@@ -25,6 +25,9 @@ const (
// ContainerStateExited indicates the the container has stopped and been
// cleaned up
ContainerStateExited ContainerStatus = iota
+ // ContainerStateRemoving indicates the container is in the process of
+ // being removed.
+ ContainerStateRemoving ContainerStatus = iota
)
// ContainerStatus returns a string representation for users
@@ -45,6 +48,8 @@ func (t ContainerStatus) String() string {
return "paused"
case ContainerStateExited:
return "exited"
+ case ContainerStateRemoving:
+ return "removing"
}
return "bad state"
}
@@ -67,6 +72,8 @@ func StringToContainerStatus(status string) (ContainerStatus, error) {
return ContainerStatePaused, nil
case ContainerStateExited.String():
return ContainerStateExited, nil
+ case ContainerStateRemoving.String():
+ return ContainerStateRemoving, nil
default:
return ContainerStateUnknown, errors.Wrapf(ErrInvalidArg, "unknown container state: %s", status)
}
diff --git a/libpod/oci_util.go b/libpod/oci_util.go
index 3345220ac..53567d2d0 100644
--- a/libpod/oci_util.go
+++ b/libpod/oci_util.go
@@ -82,18 +82,16 @@ func bindPorts(ports []ocicni.PortMapping) ([]*os.File, error) {
}
func getOCIRuntimeError(runtimeMsg string) error {
- r := strings.ToLower(runtimeMsg)
-
includeFullOutput := logrus.GetLevel() == logrus.DebugLevel
- if match := regexp.MustCompile(".*permission denied.*|.*operation not permitted.*").FindString(r); match != "" {
+ if match := regexp.MustCompile("(?i).*permission denied.*|.*operation not permitted.*").FindString(runtimeMsg); match != "" {
errStr := match
if includeFullOutput {
errStr = runtimeMsg
}
return errors.Wrapf(define.ErrOCIRuntimePermissionDenied, "%s", strings.Trim(errStr, "\n"))
}
- if match := regexp.MustCompile(".*executable file not found in.*|.*no such file or directory.*").FindString(r); match != "" {
+ if match := regexp.MustCompile("(?i).*executable file not found in.*|.*no such file or directory.*").FindString(runtimeMsg); match != "" {
errStr := match
if includeFullOutput {
errStr = runtimeMsg
diff --git a/libpod/options.go b/libpod/options.go
index f7f14eb26..a9b775dc3 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -768,16 +768,8 @@ func WithIPCNSFrom(nsCtr *Container) CtrCreateOption {
return define.ErrCtrFinalized
}
- if !nsCtr.valid {
- return define.ErrCtrRemoved
- }
-
- if nsCtr.ID() == ctr.ID() {
- return errors.Wrapf(define.ErrInvalidArg, "must specify another container")
- }
-
- if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod {
- return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID())
+ if err := checkDependencyContainer(nsCtr, ctr); err != nil {
+ return err
}
ctr.config.IPCNsCtr = nsCtr.ID()
@@ -796,16 +788,8 @@ func WithMountNSFrom(nsCtr *Container) CtrCreateOption {
return define.ErrCtrFinalized
}
- if !nsCtr.valid {
- return define.ErrCtrRemoved
- }
-
- if nsCtr.ID() == ctr.ID() {
- return errors.Wrapf(define.ErrInvalidArg, "must specify another container")
- }
-
- if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod {
- return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID())
+ if err := checkDependencyContainer(nsCtr, ctr); err != nil {
+ return err
}
ctr.config.MountNsCtr = nsCtr.ID()
@@ -824,22 +808,14 @@ func WithNetNSFrom(nsCtr *Container) CtrCreateOption {
return define.ErrCtrFinalized
}
- if !nsCtr.valid {
- return define.ErrCtrRemoved
- }
-
- if nsCtr.ID() == ctr.ID() {
- return errors.Wrapf(define.ErrInvalidArg, "must specify another container")
+ if err := checkDependencyContainer(nsCtr, ctr); err != nil {
+ return err
}
if ctr.config.CreateNetNS {
return errors.Wrapf(define.ErrInvalidArg, "cannot join another container's net ns as we are making a new net ns")
}
- if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod {
- return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID())
- }
-
ctr.config.NetNsCtr = nsCtr.ID()
return nil
@@ -856,16 +832,8 @@ func WithPIDNSFrom(nsCtr *Container) CtrCreateOption {
return define.ErrCtrFinalized
}
- if !nsCtr.valid {
- return define.ErrCtrRemoved
- }
-
- if nsCtr.ID() == ctr.ID() {
- return errors.Wrapf(define.ErrInvalidArg, "must specify another container")
- }
-
- if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod {
- return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID())
+ if err := checkDependencyContainer(nsCtr, ctr); err != nil {
+ return err
}
if ctr.config.NoCgroups {
@@ -888,16 +856,8 @@ func WithUserNSFrom(nsCtr *Container) CtrCreateOption {
return define.ErrCtrFinalized
}
- if !nsCtr.valid {
- return define.ErrCtrRemoved
- }
-
- if nsCtr.ID() == ctr.ID() {
- return errors.Wrapf(define.ErrInvalidArg, "must specify another container")
- }
-
- if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod {
- return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID())
+ if err := checkDependencyContainer(nsCtr, ctr); err != nil {
+ return err
}
ctr.config.UserNsCtr = nsCtr.ID()
@@ -917,16 +877,8 @@ func WithUTSNSFrom(nsCtr *Container) CtrCreateOption {
return define.ErrCtrFinalized
}
- if !nsCtr.valid {
- return define.ErrCtrRemoved
- }
-
- if nsCtr.ID() == ctr.ID() {
- return errors.Wrapf(define.ErrInvalidArg, "must specify another container")
- }
-
- if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod {
- return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID())
+ if err := checkDependencyContainer(nsCtr, ctr); err != nil {
+ return err
}
ctr.config.UTSNsCtr = nsCtr.ID()
@@ -945,16 +897,8 @@ func WithCgroupNSFrom(nsCtr *Container) CtrCreateOption {
return define.ErrCtrFinalized
}
- if !nsCtr.valid {
- return define.ErrCtrRemoved
- }
-
- if nsCtr.ID() == ctr.ID() {
- return errors.Wrapf(define.ErrInvalidArg, "must specify another container")
- }
-
- if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod {
- return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID())
+ if err := checkDependencyContainer(nsCtr, ctr); err != nil {
+ return err
}
ctr.config.CgroupNsCtr = nsCtr.ID()
diff --git a/libpod/reset.go b/libpod/reset.go
new file mode 100644
index 000000000..a35b476a4
--- /dev/null
+++ b/libpod/reset.go
@@ -0,0 +1,107 @@
+package libpod
+
+import (
+ "context"
+ "os"
+ "path/filepath"
+
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// Reset removes all storage
+func (r *Runtime) Reset(ctx context.Context) error {
+
+ pods, err := r.GetAllPods()
+ if err != nil {
+ return err
+ }
+ for _, p := range pods {
+ if err := r.RemovePod(ctx, p, true, true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchPod {
+ continue
+ }
+ logrus.Errorf("Error removing Pod %s: %v", p.ID(), err)
+ }
+ }
+
+ ctrs, err := r.GetAllContainers()
+ if err != nil {
+ return err
+ }
+
+ for _, c := range ctrs {
+ if err := r.RemoveContainer(ctx, c, true, true); err != nil {
+ if err := r.RemoveStorageContainer(c.ID(), true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchCtr {
+ continue
+ }
+ logrus.Errorf("Error removing container %s: %v", c.ID(), err)
+ }
+ }
+ }
+
+ if err := stopPauseProcess(); err != nil {
+ logrus.Errorf("Error stopping pause process: %v", err)
+ }
+
+ ir := r.ImageRuntime()
+ images, err := ir.GetImages()
+ if err != nil {
+ return err
+ }
+
+ for _, i := range images {
+ if err := i.Remove(ctx, true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchImage {
+ continue
+ }
+ logrus.Errorf("Error removing image %s: %v", i.ID(), err)
+ }
+ }
+ volumes, err := r.state.AllVolumes()
+ if err != nil {
+ return err
+ }
+ for _, v := range volumes {
+ if err := r.RemoveVolume(ctx, v, true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchVolume {
+ continue
+ }
+ logrus.Errorf("Error removing volume %s: %v", v.config.Name, err)
+ }
+ }
+
+ _, prevError := r.store.Shutdown(true)
+ if err := os.RemoveAll(r.store.GraphRoot()); err != nil {
+ if prevError != nil {
+ logrus.Error(prevError)
+ }
+ prevError = err
+ }
+ if err := os.RemoveAll(r.store.RunRoot()); err != nil {
+ if prevError != nil {
+ logrus.Error(prevError)
+ }
+ prevError = err
+ }
+ if err := os.RemoveAll(r.config.TmpDir); err != nil {
+ if prevError != nil {
+ logrus.Error(prevError)
+ }
+ prevError = err
+ }
+ if rootless.IsRootless() {
+ configPath := filepath.Join(os.Getenv("HOME"), ".config/containers")
+ if err := os.RemoveAll(configPath); err != nil {
+ if prevError != nil {
+ logrus.Error(prevError)
+ }
+ prevError = err
+ }
+ }
+
+ return prevError
+}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 42e6782e9..3873079ce 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -625,7 +625,8 @@ func (r *Runtime) refresh(alivePath string) error {
}
// Next refresh the state of all containers to recreate dirs and
- // namespaces, and all the pods to recreate cgroups
+ // namespaces, and all the pods to recreate cgroups.
+ // Containers, pods, and volumes must also reacquire their locks.
ctrs, err := r.state.AllContainers()
if err != nil {
return errors.Wrapf(err, "error retrieving all containers from state")
@@ -634,10 +635,14 @@ func (r *Runtime) refresh(alivePath string) error {
if err != nil {
return errors.Wrapf(err, "error retrieving all pods from state")
}
- // No locks are taken during pod and container refresh.
- // Furthermore, the pod and container refresh() functions are not
+ vols, err := r.state.AllVolumes()
+ if err != nil {
+ return errors.Wrapf(err, "error retrieving all volumes from state")
+ }
+ // No locks are taken during pod, volume, and container refresh.
+ // Furthermore, the pod/volume/container refresh() functions are not
// allowed to take locks themselves.
- // We cannot assume that any pod or container has a valid lock until
+ // We cannot assume that any pod/volume/container has a valid lock until
// after this function has returned.
// The runtime alive lock should suffice to provide mutual exclusion
// until this has run.
@@ -651,6 +656,11 @@ func (r *Runtime) refresh(alivePath string) error {
logrus.Errorf("Error refreshing pod %s: %v", pod.ID(), err)
}
}
+ for _, vol := range vols {
+ if err := vol.refresh(); err != nil {
+ logrus.Errorf("Error refreshing volume %s: %v", vol.Name(), err)
+ }
+ }
// Create a file indicating the runtime is alive and ready
file, err := os.OpenFile(alivePath, os.O_RDONLY|os.O_CREATE, 0644)
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 7069d3494..ae401013c 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -489,32 +489,19 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
}
}
- var cleanupErr error
- // Remove the container from the state
- if c.config.Pod != "" {
- // If we're removing the pod, the container will be evicted
- // from the state elsewhere
- if !removePod {
- if err := r.state.RemoveContainerFromPod(pod, c); err != nil {
- cleanupErr = err
- }
- }
- } else {
- if err := r.state.RemoveContainer(c); err != nil {
- cleanupErr = err
- }
+ // Set ContainerStateRemoving and remove exec sessions
+ c.state.State = define.ContainerStateRemoving
+ c.state.ExecSessions = nil
+
+ if err := c.save(); err != nil {
+ return errors.Wrapf(err, "unable to set container %s removing state in database", c.ID())
}
- // Set container as invalid so it can no longer be used
- c.valid = false
+ var cleanupErr error
// Clean up network namespace, cgroups, mounts
if err := c.cleanup(ctx); err != nil {
- if cleanupErr == nil {
- cleanupErr = errors.Wrapf(err, "error cleaning up container %s", c.ID())
- } else {
- logrus.Errorf("cleanup network, cgroups, mounts: %v", err)
- }
+ cleanupErr = errors.Wrapf(err, "error cleaning up container %s", c.ID())
}
// Stop the container's storage
@@ -540,6 +527,29 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
}
}
+ // Remove the container from the state
+ if c.config.Pod != "" {
+ // If we're removing the pod, the container will be evicted
+ // from the state elsewhere
+ if !removePod {
+ if err := r.state.RemoveContainerFromPod(pod, c); err != nil {
+ if cleanupErr == nil {
+ cleanupErr = err
+ } else {
+ logrus.Errorf("Error removing container %s from database: %v", c.ID(), err)
+ }
+ }
+ }
+ } else {
+ if err := r.state.RemoveContainer(c); err != nil {
+ if cleanupErr == nil {
+ cleanupErr = err
+ } else {
+ logrus.Errorf("Error removing container %s from database: %v", c.ID(), err)
+ }
+ }
+ }
+
// Deallocate the container's lock
if err := c.lock.Free(); err != nil {
if cleanupErr == nil {
@@ -549,6 +559,9 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
}
}
+ // Set container as invalid so it can no longer be used
+ c.valid = false
+
c.newContainerEvent(events.Remove)
if !removeVolume {
diff --git a/libpod/runtime_migrate_unsupported.go b/libpod/runtime_migrate_unsupported.go
index 1a9e46fdc..e362cca63 100644
--- a/libpod/runtime_migrate_unsupported.go
+++ b/libpod/runtime_migrate_unsupported.go
@@ -9,3 +9,7 @@ import (
func (r *Runtime) migrate(ctx context.Context) error {
return nil
}
+
+func stopPauseProcess() error {
+ return nil
+}
diff --git a/libpod/util.go b/libpod/util.go
index bae2f4eb8..30e5cd4c3 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -206,3 +206,28 @@ func DefaultSeccompPath() (string, error) {
}
return config.SeccompDefaultPath, nil
}
+
+// CheckDependencyContainer verifies the given container can be used as a
+// dependency of another container.
+// Both the dependency to check and the container that will be using the
+// dependency must be passed in.
+// It is assumed that ctr is locked, and depCtr is unlocked.
+func checkDependencyContainer(depCtr, ctr *Container) error {
+ state, err := depCtr.State()
+ if err != nil {
+ return errors.Wrapf(err, "error accessing dependency container %s state", depCtr.ID())
+ }
+ if state == define.ContainerStateRemoving {
+ return errors.Wrapf(define.ErrCtrStateInvalid, "cannot use container %s as a dependency as it is being removed", depCtr.ID())
+ }
+
+ if depCtr.ID() == ctr.ID() {
+ return errors.Wrapf(define.ErrInvalidArg, "must specify another container")
+ }
+
+ if ctr.config.Pod != "" && depCtr.PodID() != ctr.config.Pod {
+ return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, depCtr.ID())
+ }
+
+ return nil
+}
diff --git a/libpod/volume_internal.go b/libpod/volume_internal.go
index 42b935e7c..e89b3484d 100644
--- a/libpod/volume_internal.go
+++ b/libpod/volume_internal.go
@@ -5,6 +5,7 @@ import (
"path/filepath"
"github.com/containers/libpod/libpod/define"
+ "github.com/pkg/errors"
)
// Creates a new volume
@@ -46,3 +47,14 @@ func (v *Volume) update() error {
func (v *Volume) save() error {
return v.runtime.state.SaveVolume(v)
}
+
+// Refresh volume state after a restart.
+func (v *Volume) refresh() error {
+ lock, err := v.runtime.lockManager.AllocateAndRetrieveLock(v.config.LockID)
+ if err != nil {
+ return errors.Wrapf(err, "error acquiring lock %d for volume %s", v.config.LockID, v.Name())
+ }
+ v.lock = lock
+
+ return nil
+}
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index bc9554193..0c73977c7 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -461,7 +461,8 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode
if c.IsSet("rm") {
if err := r.Runtime.RemoveContainer(ctx, ctr, false, true); err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
+ if errors.Cause(err) == define.ErrNoSuchCtr ||
+ errors.Cause(err) == define.ErrCtrRemoved {
logrus.Warnf("Container %s does not exist: %v", ctr.ID(), err)
} else {
logrus.Errorf("Error removing container %s: %v", ctr.ID(), err)
@@ -1009,16 +1010,30 @@ func (r *LocalRuntime) ExecContainer(ctx context.Context, cli *cliconfig.ExecVal
}
// Prune removes stopped containers
-func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) {
+func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool, filters []string) ([]string, map[string]error, error) {
var (
- ok = []string{}
- failures = map[string]error{}
- err error
+ ok = []string{}
+ failures = map[string]error{}
+ err error
+ filterFunc []libpod.ContainerFilter
)
logrus.Debugf("Setting maximum rm workers to %d", maxWorkers)
- filter := func(c *libpod.Container) bool {
+ for _, filter := range filters {
+ filterSplit := strings.SplitN(filter, "=", 2)
+ if len(filterSplit) < 2 {
+ return ok, failures, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", filter)
+ }
+
+ f, err := shared.GenerateContainerFilterFuncs(filterSplit[0], filterSplit[1], r.Runtime)
+ if err != nil {
+ return ok, failures, err
+ }
+ filterFunc = append(filterFunc, f)
+ }
+
+ containerStateFilter := func(c *libpod.Container) bool {
state, err := c.State()
if err != nil {
logrus.Error(err)
@@ -1032,7 +1047,9 @@ func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([
}
return false
}
- delContainers, err := r.Runtime.GetContainers(filter)
+ filterFunc = append(filterFunc, containerStateFilter)
+
+ delContainers, err := r.Runtime.GetContainers(filterFunc...)
if err != nil {
return ok, failures, err
}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index e34b8ffd9..36db4af68 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -922,7 +922,7 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
}
// Prune removes stopped containers
-func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) {
+func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool, filter []string) ([]string, map[string]error, error) {
var (
ok = []string{}
diff --git a/pkg/adapter/reset.go b/pkg/adapter/reset.go
new file mode 100644
index 000000000..0decc3d15
--- /dev/null
+++ b/pkg/adapter/reset.go
@@ -0,0 +1,13 @@
+// +build !remoteclient
+
+package adapter
+
+import (
+ "context"
+)
+
+// Reset the container storage back to initial states.
+// Removes all Pods, Containers, Images and Volumes.
+func (r *LocalRuntime) Reset() error {
+ return r.Runtime.Reset(context.TODO())
+}
diff --git a/pkg/adapter/reset_remote.go b/pkg/adapter/reset_remote.go
new file mode 100644
index 000000000..663fab639
--- /dev/null
+++ b/pkg/adapter/reset_remote.go
@@ -0,0 +1,12 @@
+// +build remoteclient
+
+package adapter
+
+import (
+ "github.com/containers/libpod/cmd/podman/varlink"
+)
+
+// Info returns information for the host system and its components
+func (r RemoteRuntime) Reset() error {
+ return iopodman.Reset().Call(r.Conn)
+}
diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go
index f6057f5fc..b81ff11ba 100644
--- a/pkg/varlinkapi/system.go
+++ b/pkg/varlinkapi/system.go
@@ -3,12 +3,15 @@
package varlinkapi
import (
+ "context"
"fmt"
- "github.com/containers/libpod/libpod/define"
+ "os"
goruntime "runtime"
"time"
"github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/sirupsen/logrus"
)
// GetVersion ...
@@ -105,3 +108,20 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error {
podmanInfo.Insecure_registries = insecureRegistries
return call.ReplyGetInfo(podmanInfo)
}
+
+// GetVersion ...
+func (i *LibpodAPI) Reset(call iopodman.VarlinkCall) error {
+ if err := i.Runtime.Reset(context.TODO()); err != nil {
+ logrus.Errorf("Reset Failed: %v", err)
+ if err := call.ReplyErrorOccurred(err.Error()); err != nil {
+ logrus.Errorf("Failed to send ReplyErrorOccurred: %v", err)
+ }
+ os.Exit(define.ExecErrorCodeGeneric)
+ }
+ if err := call.ReplyReset(); err != nil {
+ logrus.Errorf("Failed to send ReplyReset: %v", err)
+ os.Exit(define.ExecErrorCodeGeneric)
+ }
+ os.Exit(0)
+ return nil
+}
diff --git a/rootless.md b/rootless.md
index 4fb3c7deb..69de6db21 100644
--- a/rootless.md
+++ b/rootless.md
@@ -42,3 +42,5 @@ can easily fail
* Pause and Unpause (Works with cgroup V2 support)
* Issues with higher UIDs can cause builds to fail
* If a build is attempting to use a UID that is not mapped into the user namespace mapping for a container, then builds will not be able to put the UID in an image.
+* Making device nodes within a container fails, even when running --privileged.
+ * Kernel does not allow non root user processes (processes without CAP_MKNOD) to create device nodes. If container needs to create device nodes, it must be run as root.
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 5239f4d8e..43f08bf03 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -135,3 +135,7 @@ func removeCache() {
func (p *PodmanTestIntegration) SeedImages() error {
return nil
}
+
+// We don't support running Varlink when local
+func (p *PodmanTestIntegration) StartVarlink() {
+}
diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go
index 16522785b..c9b01ad4a 100644
--- a/test/e2e/prune_test.go
+++ b/test/e2e/prune_test.go
@@ -52,7 +52,7 @@ var _ = Describe("Podman prune", func() {
stop.WaitWithDefaultTimeout()
Expect(stop.ExitCode()).To(Equal(0))
- prune := podmanTest.Podman([]string{"container", "prune"})
+ prune := podmanTest.Podman([]string{"container", "prune", "-f"})
prune.WaitWithDefaultTimeout()
Expect(prune.ExitCode()).To(Equal(0))
diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go
new file mode 100644
index 000000000..e5ce69739
--- /dev/null
+++ b/test/e2e/system_reset_test.go
@@ -0,0 +1,83 @@
+package integration
+
+import (
+ "fmt"
+ "os"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("podman system reset", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds())
+ GinkgoWriter.Write([]byte(timedResult))
+ })
+
+ It("podman system reset", func() {
+ // system reset will not remove additional store images, so need to grab length
+
+ session := podmanTest.Podman([]string{"rmi", "--force", "--all"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"images", "-n"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ l := len(session.OutputToStringArray())
+
+ session = podmanTest.Podman([]string{"pull", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"volume", "create", "data"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"create", "-v", "data:/data", ALPINE, "echo", "hello"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"system", "reset", "-f"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // If remote then the varlink service should have exited
+ // On local tests this is a noop
+ podmanTest.StartVarlink()
+
+ session = podmanTest.Podman([]string{"images", "-n"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(len(session.OutputToStringArray())).To(Equal(l))
+
+ session = podmanTest.Podman([]string{"volume", "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(len(session.OutputToStringArray())).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"container", "ls", "-q"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(len(session.OutputToStringArray())).To(Equal(0))
+ })
+})
diff --git a/test/e2e/version_test.go b/test/e2e/version_test.go
index 0db2e2cf2..c2af613aa 100644
--- a/test/e2e/version_test.go
+++ b/test/e2e/version_test.go
@@ -33,7 +33,6 @@ var _ = Describe("Podman version", func() {
})
It("podman version", func() {
- SkipIfRemote()
session := podmanTest.Podman([]string{"version"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -43,7 +42,6 @@ var _ = Describe("Podman version", func() {
})
It("podman -v", func() {
- SkipIfRemote()
session := podmanTest.Podman([]string{"-v"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -52,7 +50,6 @@ var _ = Describe("Podman version", func() {
})
It("podman --version", func() {
- SkipIfRemote()
session := podmanTest.Podman([]string{"--version"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -61,7 +58,6 @@ var _ = Describe("Podman version", func() {
})
It("podman version --format json", func() {
- SkipIfRemote()
session := podmanTest.Podman([]string{"version", "--format", "json"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -69,7 +65,6 @@ var _ = Describe("Podman version", func() {
})
It("podman version --format json", func() {
- SkipIfRemote()
session := podmanTest.Podman([]string{"version", "--format", "{{ json .}}"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -77,8 +72,15 @@ var _ = Describe("Podman version", func() {
})
It("podman version --format GO template", func() {
- SkipIfRemote()
- session := podmanTest.Podman([]string{"version", "--format", "{{ .Version }}"})
+ session := podmanTest.Podman([]string{"version", "--format", "{{ .Client.Version }}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"version", "--format", "{{ .Server.Version }}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"version", "--format", "{{ .Version }}"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})