Skip to content

Commit

Permalink
podman system prune support prune unused networks
Browse files Browse the repository at this point in the history
This is an enhancement for the podman system prune feature.

In this issue, it is mentioned that 'network prune' should be
wired into 'podman system prune'
containers#8673

Does not remove cni networks because it could remove external cni networks.

Therefore, I add the function to remove unused netavark networks.

Signed-off-by: Toshiki Sonoda <sonoda.toshiki@fujitsu.com>
  • Loading branch information
sstosh committed Jun 13, 2022
1 parent c044d45 commit c169680
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 18 deletions.
10 changes: 8 additions & 2 deletions cmd/podman/system/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func prune(cmd *cobra.Command, args []string) error {
}
}

// Remove all unused pods, containers, images, netavark networks, and volume data.
pruneOptions.Filters, err = parse.FilterArgumentsIntoFilters(filters)
if err != nil {
return err
Expand Down Expand Up @@ -106,6 +107,11 @@ func prune(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
// Print netavark Network prune results
err = utils.PrintNetworkPruneResults(response.NetworkPruneReports, true)
if err != nil {
return err
}

fmt.Printf("Total reclaimed space: %s\n", units.HumanSize((float64)(response.ReclaimedSpace)))
return nil
Expand All @@ -115,15 +121,15 @@ func createPruneWarningMessage(pruneOpts entities.SystemPruneOptions) string {
if pruneOpts.All {
return `WARNING! This command removes:
- all stopped containers
- all networks not used by at least one container%s
- all netavark networks not used by at least one container%s
- all images without at least one container associated with them
- all build cache
%s`
}
return `WARNING! This command removes:
- all stopped containers
- all networks not used by at least one container%s
- all netavark networks not used by at least one container%s
- all dangling images
- all dangling build cache
Expand Down
15 changes: 15 additions & 0 deletions cmd/podman/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,18 @@ func PrintImagePruneResults(imagePruneReports []*reports.PruneReport, heading bo

return nil
}

func PrintNetworkPruneResults(networkPruneReport []*reports.PruneReport, heading bool) error {
var errs OutputErrors
if heading && len(networkPruneReport) > 0 {
fmt.Println("Deleted netavark Networks")
}
for _, r := range networkPruneReport {
if r.Err == nil {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Err)
}
}
return errs.PrintErrors()
}
6 changes: 3 additions & 3 deletions docs/source/markdown/podman-system-prune.1.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
% podman-system-prune(1)

## NAME
podman\-system\-prune - Remove all unused pod, container, image and volume data
podman\-system\-prune - Remove all unused pods, containers, images, netavark networks, and volume data

## SYNOPSIS
**podman system prune** [*options*]

## DESCRIPTION
**podman system prune** removes all unused containers (both dangling and unreferenced), pods and optionally, volumes from local storage.
**podman system prune** removes all unused containers (both dangling and unreferenced), pods, netavark networks, and optionally, volumes from local storage.

With the **--all** option, you can delete all unused images. Unused images are dangling images as well as any image that does not have any containers based on it.

Expand All @@ -16,7 +16,7 @@ By default, volumes are not removed to prevent important data from being deleted
## OPTIONS
#### **--all**, **-a**

Recursively remove all unused pod, container, image and volume data (Maximum 50 iterations.)
Recursively remove all unused pods, containers, images, netavark networks, and volume data. (Maximum 50 iterations.)

#### **--filter**=*filters*

Expand Down
20 changes: 10 additions & 10 deletions docs/source/markdown/podman-system.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ The system command allows you to manage the podman systems

## COMMANDS

| Command | Man Page | Description |
| ------- | ------------------------------------------------------------ | -------------------------------------------------------------------- |
| connection | [podman-system-connection(1)](podman-system-connection.1.md) | Manage the destination(s) for Podman service(s) |
| 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. |
| 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 pod, 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. |
| service | [podman-system-service(1)](podman-system-service.1.md) | Run an API service |
| Command | Man Page | Description |
| ------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| connection | [podman-system-connection(1)](podman-system-connection.1.md) | Manage the destination(s) for Podman service(s) |
| 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. |
| 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 pods, containers, images, netavark networks, 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. |
| service | [podman-system-service(1)](podman-system-service.1.md) | Run an API service |

## SEE ALSO
**[podman(1)](podman.1.md)**
5 changes: 5 additions & 0 deletions libpod/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,11 @@ func (r *Runtime) GetDefaultNetworkName() string {
return r.config.Network.DefaultNetwork
}

// GetNetworkBackend returns the network interface which is used by the runtime
func (r *Runtime) GetNetworkBackend() string {
return r.config.Network.NetworkBackend
}

// RemoteURI returns the API server URI
func (r *Runtime) RemoteURI() string {
return r.config.Engine.RemoteURI
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/entities/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type SystemPruneReport struct {
PodPruneReport []*PodPruneReport
ContainerPruneReports []*reports.PruneReport
ImagePruneReports []*reports.PruneReport
NetworkPruneReports []*reports.PruneReport
VolumePruneReports []*reports.PruneReport
ReclaimedSpace uint64
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/domain/infra/abi/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (ic *ContainerEngine) NetworkExists(ctx context.Context, networkname string
}, nil
}

// Network prune removes unused cni networks
// Network prune removes unused networks
func (ic *ContainerEngine) NetworkPrune(ctx context.Context, options entities.NetworkPruneOptions) ([]*entities.NetworkPruneReport, error) {
cons, err := ic.Libpod.GetAllContainers()
if err != nil {
Expand Down
65 changes: 63 additions & 2 deletions pkg/domain/infra/abi/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"os/exec"
"path/filepath"

"github.com/containers/common/libnetwork/types"
netutil "github.com/containers/common/libnetwork/util"
"github.com/containers/common/pkg/cgroups"
"github.com/containers/common/pkg/config"
cutil "github.com/containers/common/pkg/util"
Expand Down Expand Up @@ -137,7 +139,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, noMoveProcess bool)
return nil
}

// SystemPrune removes unused data from the system. Pruning pods, containers, volumes and images.
// SystemPrune removes unused data from the system. Pruning pods, containers, netavark networks, volumes and images.
func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.SystemPruneOptions) (*entities.SystemPruneReport, error) {
var systemPruneReport = new(entities.SystemPruneReport)
filters := []string{}
Expand All @@ -148,25 +150,32 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
found := true
for found {
found = false

// TODO: Figure out cleaner way to handle all of the different PruneOptions
// Remove all unused pods.
podPruneReport, err := ic.prunePodHelper(ctx)
if err != nil {
return nil, err
}
if len(podPruneReport) > 0 {
found = true
}

systemPruneReport.PodPruneReport = append(systemPruneReport.PodPruneReport, podPruneReport...)

// TODO: Figure out cleaner way to handle all of the different PruneOptions
// Remove all unused containers.
containerPruneOptions := entities.ContainerPruneOptions{}
containerPruneOptions.Filters = (url.Values)(options.Filters)

containerPruneReports, err := ic.ContainerPrune(ctx, containerPruneOptions)
if err != nil {
return nil, err
}

reclaimedSpace += reports.PruneReportsSize(containerPruneReports)
systemPruneReport.ContainerPruneReports = append(systemPruneReport.ContainerPruneReports, containerPruneReports...)

// Remove all unused images.
imagePruneOptions := entities.ImagePruneOptions{
All: options.All,
Filter: filters,
Expand All @@ -183,6 +192,58 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
}

systemPruneReport.ImagePruneReports = append(systemPruneReport.ImagePruneReports, imagePruneReports...)

// Remove all unused netavark networks.
// Does not remove cni networks because it could remove external cni networks.
if ic.Libpod.GetNetworkBackend() == "netavark" {
cons, err := ic.Libpod.GetAllContainers()
if err != nil {
return nil, err
}
// Gather up all the non-default networks that the
// containers want
networksToKeep := make(map[string]bool)
for _, c := range cons {
nets, err := c.Networks()
if err != nil {
return nil, err
}
for _, n := range nets {
networksToKeep[n] = true
}
}
// ignore the default network, this one cannot be deleted
networksToKeep[ic.Libpod.GetDefaultNetworkName()] = true

// get all filters
filters, err := netutil.GenerateNetworkPruneFilters(options.Filters)
if err != nil {
return nil, err
}
danglingFilterFunc := func(net types.Network) bool {
for network := range networksToKeep {
if network == net.Name {
return false
}
}
return true
}
filters = append(filters, danglingFilterFunc)
nets, err := ic.Libpod.Network().NetworkList(filters...)
if err != nil {
return nil, err
}

for _, net := range nets {
systemPruneReport.NetworkPruneReports = append(systemPruneReport.NetworkPruneReports, &reports.PruneReport{
Id: net.Name,
Err: ic.Libpod.Network().NetworkRemove(net.Name),
Size: 0,
})
}
}

// Remove unused volume data.
if options.Volume {
volumePruneOptions := entities.VolumePruneOptions{}
volumePruneOptions.Filters = (url.Values)(options.Filters)
Expand Down
28 changes: 28 additions & 0 deletions test/e2e/prune_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,34 @@ var _ = Describe("Podman prune", func() {
Expect(pods.OutputToStringArray()).To(HaveLen(2))
})

It("podman system prune networks", func() {
// About netavark network backend test.
session := podmanTest.Podman([]string{"network", "create", "test"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

session = podmanTest.Podman([]string{"system", "prune", "-f"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

// Default network should exists.
session = podmanTest.Podman([]string{"network", "ls", "-q", "--filter", "name=^podman$"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(HaveLen(1))

// Remove all unused netavark networks.
// Does not remove cni networks because it could remove external cni networks.
session = podmanTest.Podman([]string{"network", "ls", "-q", "--filter", "name=^test$"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
if podmanTest.NetworkBackend == Netavark {
Expect(session.OutputToStringArray()).To(HaveLen(0))
} else {
Expect(session.OutputToStringArray()).To(HaveLen(1))
}
})

It("podman system prune - pod,container stopped", func() {
session := podmanTest.Podman([]string{"pod", "create"})
session.WaitWithDefaultTimeout()
Expand Down

0 comments on commit c169680

Please sign in to comment.