mirror of
https://github.com/containers/podman.git
synced 2025-05-21 00:56:36 +08:00
enable podman-remote volume prune
allow users to remotely prune volumes. this is the last volume command for remote enablement. as such, the volume commands are being folded back into main because they are supported for both local and remote clients. also, enable all volume tests that do not use containers as containers are not enabled for the remote client yet. Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
15
API.md
15
API.md
@ -131,6 +131,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
|
||||
|
||||
[func VolumeRemove(options: VolumeRemoveOpts) []string](#VolumeRemove)
|
||||
|
||||
[func VolumesPrune() []string, []string](#VolumesPrune)
|
||||
|
||||
[func WaitContainer(name: string) int](#WaitContainer)
|
||||
|
||||
[type BuildInfo](#BuildInfo)
|
||||
@ -530,7 +532,7 @@ GetVersion returns version and build information of the podman service
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
method GetVolumes(args: [[]string](#[]string), all: [bool](https://godoc.org/builtin#bool)) [Volume](#Volume)</div>
|
||||
|
||||
GetVolumes gets slice of the volumes on a remote host
|
||||
### <a name="HistoryImage"></a>func HistoryImage
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
@ -773,7 +775,7 @@ the image cannot be found in local storage; otherwise it will return a [MoreResp
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
method ReceiveFile(path: [string](https://godoc.org/builtin#string), delete: [bool](https://godoc.org/builtin#bool)) [int](https://godoc.org/builtin#int)</div>
|
||||
|
||||
ReceiveFile allows the host to send a remote client a file
|
||||
### <a name="RemoveContainer"></a>func RemoveContainer
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
@ -856,7 +858,7 @@ search results per registry.
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
method SendFile(type: [string](https://godoc.org/builtin#string), length: [int](https://godoc.org/builtin#int)) [string](https://godoc.org/builtin#string)</div>
|
||||
|
||||
Sendfile allows a remote client to send a file to the host
|
||||
### <a name="StartContainer"></a>func StartContainer
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
@ -956,12 +958,17 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.UnpausePod '{"name": "foo
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
method VolumeCreate(options: [VolumeCreateOpts](#VolumeCreateOpts)) [string](https://godoc.org/builtin#string)</div>
|
||||
|
||||
VolumeCreate creates a volume on a remote host
|
||||
### <a name="VolumeRemove"></a>func VolumeRemove
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
method VolumeRemove(options: [VolumeRemoveOpts](#VolumeRemoveOpts)) [[]string](#[]string)</div>
|
||||
VolumeRemove removes a volume on a remote host
|
||||
### <a name="VolumesPrune"></a>func VolumesPrune
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
method VolumesPrune() [[]string](#[]string), [[]string](#[]string)</div>
|
||||
VolumesPrune removes unused volumes on the host
|
||||
### <a name="WaitContainer"></a>func WaitContainer
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
|
@ -114,18 +114,6 @@ func getPodSubCommands() []*cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
// Commands that the local client implements
|
||||
func getVolumeSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_volumeCreateCommand,
|
||||
_volumeLsCommand,
|
||||
_volumeRmCommand,
|
||||
_volumeInspectCommand,
|
||||
_volumePruneCommand,
|
||||
}
|
||||
}
|
||||
|
||||
// Commands that the local client implements
|
||||
func getGenerateSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_containerKubeCommand,
|
||||
|
@ -31,16 +31,6 @@ func getPodSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
// commands that only the remoteclient implements
|
||||
func getVolumeSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_volumeCreateCommand,
|
||||
_volumeRmCommand,
|
||||
_volumeLsCommand,
|
||||
_volumeInspectCommand,
|
||||
}
|
||||
}
|
||||
|
||||
// commands that only the remoteclient implements
|
||||
func getGenerateSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
|
@ -1070,15 +1070,24 @@ method ContainerInspectData(name: string) -> (config: string)
|
||||
# development of Podman only and generally should not be used.
|
||||
method ContainerStateData(name: string) -> (config: string)
|
||||
|
||||
# Sendfile allows a remote client to send a file to the host
|
||||
method SendFile(type: string, length: int) -> (file_handle: string)
|
||||
|
||||
# ReceiveFile allows the host to send a remote client a file
|
||||
method ReceiveFile(path: string, delete: bool) -> (len: int)
|
||||
|
||||
# VolumeCreate creates a volume on a remote host
|
||||
method VolumeCreate(options: VolumeCreateOpts) -> (volumeName: string)
|
||||
|
||||
# VolumeRemove removes a volume on a remote host
|
||||
method VolumeRemove(options: VolumeRemoveOpts) -> (volumeNames: []string)
|
||||
|
||||
# GetVolumes gets slice of the volumes on a remote host
|
||||
method GetVolumes(args: []string, all: bool) -> (volumes: []Volume)
|
||||
|
||||
# VolumesPrune removes unused volumes on the host
|
||||
method VolumesPrune() -> (prunedNames: []string, prunedErrors: []string)
|
||||
|
||||
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
|
||||
error ImageNotFound (id: string)
|
||||
|
||||
|
@ -16,8 +16,16 @@ var volumeCommand = cliconfig.PodmanCommand{
|
||||
Long: volumeDescription,
|
||||
},
|
||||
}
|
||||
var volumeSubcommands = []*cobra.Command{
|
||||
_volumeCreateCommand,
|
||||
_volumeLsCommand,
|
||||
_volumeRmCommand,
|
||||
_volumeInspectCommand,
|
||||
_volumePruneCommand,
|
||||
}
|
||||
|
||||
func init() {
|
||||
volumeCommand.AddCommand(getVolumeSubCommands()...)
|
||||
volumeCommand.SetUsageTemplate(UsageTemplate())
|
||||
volumeCommand.AddCommand(volumeSubcommands...)
|
||||
rootCmd.AddCommand(volumeCommand.Command)
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -44,23 +43,20 @@ func init() {
|
||||
}
|
||||
|
||||
func volumePrune(runtime *adapter.LocalRuntime, ctx context.Context) error {
|
||||
var lastError error
|
||||
|
||||
volumes, err := runtime.GetAllVolumes()
|
||||
if err != nil {
|
||||
return err
|
||||
prunedNames, prunedErrors := runtime.PruneVolumes(ctx)
|
||||
for _, name := range prunedNames {
|
||||
fmt.Println(name)
|
||||
}
|
||||
if len(prunedErrors) == 0 {
|
||||
return nil
|
||||
}
|
||||
// Grab the last error
|
||||
lastError := prunedErrors[len(prunedErrors)-1]
|
||||
// Remove the last error from the error slice
|
||||
prunedErrors = prunedErrors[:len(prunedErrors)-1]
|
||||
|
||||
for _, vol := range volumes {
|
||||
err = runtime.RemoveVolume(ctx, vol, false, true)
|
||||
if err == nil {
|
||||
fmt.Println(vol.Name())
|
||||
} else if err != libpod.ErrVolumeBeingUsed {
|
||||
if lastError != nil {
|
||||
logrus.Errorf("%q", lastError)
|
||||
}
|
||||
lastError = errors.Wrapf(err, "failed to remove volume %q", vol.Name())
|
||||
}
|
||||
for _, err := range prunedErrors {
|
||||
logrus.Errorf("%q", err)
|
||||
}
|
||||
return lastError
|
||||
}
|
||||
@ -85,6 +81,5 @@ func volumePruneCmd(c *cliconfig.VolumePruneValues) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return volumePrune(runtime, getContext())
|
||||
}
|
||||
|
@ -305,3 +305,8 @@ func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, opti
|
||||
|
||||
return r.Runtime.Build(ctx, options, dockerfiles...)
|
||||
}
|
||||
|
||||
// PruneVolumes is a wrapper function for libpod PruneVolumes
|
||||
func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) {
|
||||
return r.Runtime.PruneVolumes(ctx)
|
||||
}
|
||||
|
@ -642,3 +642,17 @@ func varlinkVolumeToVolume(r *LocalRuntime, volumes []iopodman.Volume) []*Volume
|
||||
}
|
||||
return vols
|
||||
}
|
||||
|
||||
// PruneVolumes removes all unused volumes from the remote system
|
||||
func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) {
|
||||
var errs []error
|
||||
prunedNames, prunedErrors, err := iopodman.VolumesPrune().Call(r.Conn)
|
||||
if err != nil {
|
||||
return []string{}, []error{err}
|
||||
}
|
||||
// We need to transform the string results of the error into actual error types
|
||||
for _, e := range prunedErrors {
|
||||
errs = append(errs, errors.New(e))
|
||||
}
|
||||
return prunedNames, errs
|
||||
}
|
||||
|
@ -154,3 +154,27 @@ func (r *Runtime) GetAllVolumes() ([]*Volume, error) {
|
||||
|
||||
return r.state.AllVolumes()
|
||||
}
|
||||
|
||||
// PruneVolumes removes unused volumes from the system
|
||||
func (r *Runtime) PruneVolumes(ctx context.Context) ([]string, []error) {
|
||||
var (
|
||||
prunedIDs []string
|
||||
pruneErrors []error
|
||||
)
|
||||
vols, err := r.GetAllVolumes()
|
||||
if err != nil {
|
||||
pruneErrors = append(pruneErrors, err)
|
||||
return nil, pruneErrors
|
||||
}
|
||||
|
||||
for _, vol := range vols {
|
||||
if err := r.RemoveVolume(ctx, vol, false, true); err != nil {
|
||||
if err != ErrVolumeBeingUsed {
|
||||
pruneErrors = append(pruneErrors, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
prunedIDs = append(prunedIDs, vol.Name())
|
||||
}
|
||||
return prunedIDs, pruneErrors
|
||||
}
|
||||
|
@ -72,3 +72,19 @@ func (i *LibpodAPI) GetVolumes(call iopodman.VarlinkCall, args []string, all boo
|
||||
}
|
||||
return call.ReplyGetVolumes(volumes)
|
||||
}
|
||||
|
||||
// VolumesPrune removes unused images via a varlink call
|
||||
func (i *LibpodAPI) VolumesPrune(call iopodman.VarlinkCall) error {
|
||||
var errs []string
|
||||
prunedNames, prunedErrors := i.Runtime.PruneVolumes(getContext())
|
||||
if len(prunedErrors) == 0 {
|
||||
return call.ReplyVolumesPrune(prunedNames, []string{})
|
||||
}
|
||||
|
||||
// We need to take the errors and capture their strings to go back over
|
||||
// varlink
|
||||
for _, e := range prunedErrors {
|
||||
errs = append(errs, e.Error())
|
||||
}
|
||||
return call.ReplyVolumesPrune(prunedNames, errs)
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
// +build !remoteclient
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
|
@ -1,5 +1,3 @@
|
||||
// +build !remoteclient
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
|
@ -1,5 +1,3 @@
|
||||
// +build !remoteclient
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
|
@ -1,5 +1,3 @@
|
||||
// +build !remoteclient
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
@ -50,6 +48,7 @@ var _ = Describe("Podman volume rm", func() {
|
||||
})
|
||||
|
||||
It("podman rm with --force flag", func() {
|
||||
SkipIfRemote()
|
||||
session := podmanTest.Podman([]string{"create", "-v", "myvol:/myvol", ALPINE, "ls"})
|
||||
cid := session.OutputToString()
|
||||
session.WaitWithDefaultTimeout()
|
||||
|
Reference in New Issue
Block a user