podman system prune support prune unused networks

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'
https://github.com/containers/podman/issues/8673

Therefore, I add the function to remove unused networks.

Signed-off-by: Toshiki Sonoda <sonoda.toshiki@fujitsu.com>
This commit is contained in:
Toshiki Sonoda
2022-06-14 14:04:03 +09:00
parent c044d455a1
commit 4811cb110a
8 changed files with 93 additions and 18 deletions

View File

@ -75,6 +75,7 @@ func prune(cmd *cobra.Command, args []string) error {
} }
} }
// Remove all unused pods, containers, images, networks, and volume data.
pruneOptions.Filters, err = parse.FilterArgumentsIntoFilters(filters) pruneOptions.Filters, err = parse.FilterArgumentsIntoFilters(filters)
if err != nil { if err != nil {
return err return err
@ -106,6 +107,11 @@ func prune(cmd *cobra.Command, args []string) error {
if err != nil { if err != nil {
return err return err
} }
// Print 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))) fmt.Printf("Total reclaimed space: %s\n", units.HumanSize((float64)(response.ReclaimedSpace)))
return nil return nil

View File

@ -84,3 +84,18 @@ func PrintImagePruneResults(imagePruneReports []*reports.PruneReport, heading bo
return nil return nil
} }
func PrintNetworkPruneResults(networkPruneReport []*reports.PruneReport, heading bool) error {
var errs OutputErrors
if heading && len(networkPruneReport) > 0 {
fmt.Println("Deleted Networks")
}
for _, r := range networkPruneReport {
if r.Err == nil {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Err)
}
}
return errs.PrintErrors()
}

View File

@ -1,13 +1,13 @@
% podman-system-prune(1) % podman-system-prune(1)
## NAME ## NAME
podman\-system\-prune - Remove all unused pod, container, image and volume data podman\-system\-prune - Remove all unused pods, containers, images, networks, and volume data
## SYNOPSIS ## SYNOPSIS
**podman system prune** [*options*] **podman system prune** [*options*]
## DESCRIPTION ## 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, 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. 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.
@ -16,7 +16,7 @@ By default, volumes are not removed to prevent important data from being deleted
## OPTIONS ## OPTIONS
#### **--all**, **-a** #### **--all**, **-a**
Recursively remove all unused pod, container, image and volume data (Maximum 50 iterations.) Recursively remove all unused pods, containers, images, networks, and volume data. (Maximum 50 iterations.)
#### **--filter**=*filters* #### **--filter**=*filters*

View File

@ -11,16 +11,16 @@ The system command allows you to manage the podman systems
## COMMANDS ## COMMANDS
| Command | Man Page | Description | | Command | Man Page | Description |
| ------- | ------------------------------------------------------------ | -------------------------------------------------------------------- | | ------- | ------------------------------------------------------------ | ------------------------------------------------------------------------ |
| connection | [podman-system-connection(1)](podman-system-connection.1.md) | Manage the destination(s) for Podman service(s) | | 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. | | 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. | | 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. | | 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. | | prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused pods, containers, images, 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. | | 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. | | 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 | | service | [podman-system-service(1)](podman-system-service.1.md) | Run an API service |
## SEE ALSO ## SEE ALSO
**[podman(1)](podman.1.md)** **[podman(1)](podman.1.md)**

View File

@ -28,6 +28,7 @@ type SystemPruneReport struct {
PodPruneReport []*PodPruneReport PodPruneReport []*PodPruneReport
ContainerPruneReports []*reports.PruneReport ContainerPruneReports []*reports.PruneReport
ImagePruneReports []*reports.PruneReport ImagePruneReports []*reports.PruneReport
NetworkPruneReports []*reports.PruneReport
VolumePruneReports []*reports.PruneReport VolumePruneReports []*reports.PruneReport
ReclaimedSpace uint64 ReclaimedSpace uint64
} }

View File

@ -142,7 +142,7 @@ func (ic *ContainerEngine) NetworkExists(ctx context.Context, networkname string
}, nil }, 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) { func (ic *ContainerEngine) NetworkPrune(ctx context.Context, options entities.NetworkPruneOptions) ([]*entities.NetworkPruneReport, error) {
cons, err := ic.Libpod.GetAllContainers() cons, err := ic.Libpod.GetAllContainers()
if err != nil { if err != nil {

View File

@ -137,7 +137,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, noMoveProcess bool)
return nil 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, networks, volumes and images.
func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.SystemPruneOptions) (*entities.SystemPruneReport, error) { func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.SystemPruneOptions) (*entities.SystemPruneReport, error) {
var systemPruneReport = new(entities.SystemPruneReport) var systemPruneReport = new(entities.SystemPruneReport)
filters := []string{} filters := []string{}
@ -148,6 +148,9 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
found := true found := true
for found { for found {
found = false found = false
// TODO: Figure out cleaner way to handle all of the different PruneOptions
// Remove all unused pods.
podPruneReport, err := ic.prunePodHelper(ctx) podPruneReport, err := ic.prunePodHelper(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -155,9 +158,10 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
if len(podPruneReport) > 0 { if len(podPruneReport) > 0 {
found = true found = true
} }
systemPruneReport.PodPruneReport = append(systemPruneReport.PodPruneReport, podPruneReport...) 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 := entities.ContainerPruneOptions{}
containerPruneOptions.Filters = (url.Values)(options.Filters) containerPruneOptions.Filters = (url.Values)(options.Filters)
@ -165,16 +169,18 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
if err != nil { if err != nil {
return nil, err return nil, err
} }
reclaimedSpace += reports.PruneReportsSize(containerPruneReports) reclaimedSpace += reports.PruneReportsSize(containerPruneReports)
systemPruneReport.ContainerPruneReports = append(systemPruneReport.ContainerPruneReports, containerPruneReports...) systemPruneReport.ContainerPruneReports = append(systemPruneReport.ContainerPruneReports, containerPruneReports...)
// Remove all unused images.
imagePruneOptions := entities.ImagePruneOptions{ imagePruneOptions := entities.ImagePruneOptions{
All: options.All, All: options.All,
Filter: filters, Filter: filters,
} }
imageEngine := ImageEngine{Libpod: ic.Libpod} imageEngine := ImageEngine{Libpod: ic.Libpod}
imagePruneReports, err := imageEngine.Prune(ctx, imagePruneOptions) imagePruneReports, err := imageEngine.Prune(ctx, imagePruneOptions)
reclaimedSpace += reports.PruneReportsSize(imagePruneReports)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -182,10 +188,33 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
found = true found = true
} }
reclaimedSpace += reports.PruneReportsSize(imagePruneReports)
systemPruneReport.ImagePruneReports = append(systemPruneReport.ImagePruneReports, imagePruneReports...) systemPruneReport.ImagePruneReports = append(systemPruneReport.ImagePruneReports, imagePruneReports...)
// Remove all unused networks.
networkPruneOptions := entities.NetworkPruneOptions{}
networkPruneOptions.Filters = options.Filters
networkPruneReport, err := ic.NetworkPrune(ctx, networkPruneOptions)
if err != nil {
return nil, err
}
if len(networkPruneReport) > 0 {
found = true
}
for _, net := range networkPruneReport {
systemPruneReport.NetworkPruneReports = append(systemPruneReport.NetworkPruneReports, &reports.PruneReport{
Id: net.Name,
Err: net.Error,
Size: 0,
})
}
// Remove unused volume data.
if options.Volume { if options.Volume {
volumePruneOptions := entities.VolumePruneOptions{} volumePruneOptions := entities.VolumePruneOptions{}
volumePruneOptions.Filters = (url.Values)(options.Filters) volumePruneOptions.Filters = (url.Values)(options.Filters)
volumePruneReport, err := ic.VolumePrune(ctx, volumePruneOptions) volumePruneReport, err := ic.VolumePrune(ctx, volumePruneOptions)
if err != nil { if err != nil {
return nil, err return nil, err
@ -193,6 +222,7 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
if len(volumePruneReport) > 0 { if len(volumePruneReport) > 0 {
found = true found = true
} }
reclaimedSpace += reports.PruneReportsSize(volumePruneReport) reclaimedSpace += reports.PruneReportsSize(volumePruneReport)
systemPruneReport.VolumePruneReports = append(systemPruneReport.VolumePruneReports, volumePruneReport...) systemPruneReport.VolumePruneReports = append(systemPruneReport.VolumePruneReports, volumePruneReport...)
} }

View File

@ -258,6 +258,29 @@ var _ = Describe("Podman prune", func() {
Expect(pods.OutputToStringArray()).To(HaveLen(2)) 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 networks.
session = podmanTest.Podman([]string{"network", "ls", "-q", "--filter", "name=^test$"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(HaveLen(0))
})
It("podman system prune - pod,container stopped", func() { It("podman system prune - pod,container stopped", func() {
session := podmanTest.Podman([]string{"pod", "create"}) session := podmanTest.Podman([]string{"pod", "create"})
session.WaitWithDefaultTimeout() session.WaitWithDefaultTimeout()