2018-02-05 21:05:59 +00:00
|
|
|
package daemon // import "github.com/docker/docker/daemon"
|
2016-08-23 23:24:15 +00:00
|
|
|
|
|
|
|
import (
|
2018-04-19 22:30:59 +00:00
|
|
|
"context"
|
2016-08-23 23:24:15 +00:00
|
|
|
"fmt"
|
2017-04-12 20:59:31 +00:00
|
|
|
|
2021-06-23 13:26:54 +00:00
|
|
|
"github.com/docker/docker/api/server/router/system"
|
2016-08-23 23:24:15 +00:00
|
|
|
"github.com/docker/docker/api/types"
|
2022-11-29 15:46:19 +00:00
|
|
|
"github.com/docker/docker/api/types/filters"
|
2022-03-18 15:33:43 +00:00
|
|
|
"github.com/docker/docker/api/types/volume"
|
2022-11-29 15:46:19 +00:00
|
|
|
"github.com/pkg/errors"
|
2021-08-04 16:42:50 +00:00
|
|
|
"golang.org/x/sync/errgroup"
|
2016-08-23 23:24:15 +00:00
|
|
|
)
|
|
|
|
|
2022-11-29 15:46:19 +00:00
|
|
|
// containerDiskUsage obtains information about container data disk usage
|
|
|
|
// and makes sure that only one calculation is performed at the same time.
|
|
|
|
func (daemon *Daemon) containerDiskUsage(ctx context.Context) ([]*types.Container, error) {
|
|
|
|
res, _, err := daemon.usageContainers.Do(ctx, struct{}{}, func(ctx context.Context) ([]*types.Container, error) {
|
2021-06-24 17:06:17 +00:00
|
|
|
// Retrieve container list
|
2022-11-29 15:46:19 +00:00
|
|
|
containers, err := daemon.Containers(ctx, &types.ContainerListOptions{
|
2021-06-24 17:06:17 +00:00
|
|
|
Size: true,
|
|
|
|
All: true,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to retrieve container list: %v", err)
|
|
|
|
}
|
|
|
|
return containers, nil
|
|
|
|
})
|
2022-11-29 15:46:19 +00:00
|
|
|
return res, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// imageDiskUsage obtains information about image data disk usage from image service
|
|
|
|
// and makes sure that only one calculation is performed at the same time.
|
|
|
|
func (daemon *Daemon) imageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) {
|
|
|
|
imgs, _, err := daemon.usageImages.Do(ctx, struct{}{}, func(ctx context.Context) ([]*types.ImageSummary, error) {
|
|
|
|
// Get all top images with extra attributes
|
|
|
|
imgs, err := daemon.imageService.Images(ctx, types.ImageListOptions{
|
|
|
|
Filters: filters.NewArgs(),
|
|
|
|
SharedSize: true,
|
|
|
|
ContainerCount: true,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "failed to retrieve image list")
|
2021-06-24 17:06:17 +00:00
|
|
|
}
|
2022-11-29 15:46:19 +00:00
|
|
|
return imgs, nil
|
|
|
|
})
|
|
|
|
|
|
|
|
return imgs, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// localVolumesSize obtains information about volume disk usage from volumes service
|
|
|
|
// and makes sure that only one size calculation is performed at the same time.
|
|
|
|
func (daemon *Daemon) localVolumesSize(ctx context.Context) ([]*volume.Volume, error) {
|
|
|
|
volumes, _, err := daemon.usageVolumes.Do(ctx, struct{}{}, func(ctx context.Context) ([]*volume.Volume, error) {
|
|
|
|
volumes, err := daemon.volumes.LocalVolumesSize(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return volumes, nil
|
|
|
|
})
|
|
|
|
return volumes, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// layerDiskUsage obtains information about layer disk usage from image service
|
|
|
|
// and makes sure that only one size calculation is performed at the same time.
|
|
|
|
func (daemon *Daemon) layerDiskUsage(ctx context.Context) (int64, error) {
|
|
|
|
usage, _, err := daemon.usageLayer.Do(ctx, struct{}{}, func(ctx context.Context) (int64, error) {
|
|
|
|
usage, err := daemon.imageService.LayerDiskUsage(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return usage, nil
|
|
|
|
})
|
|
|
|
return usage, err
|
2021-06-24 17:06:17 +00:00
|
|
|
}
|
2017-04-12 20:59:59 +00:00
|
|
|
|
2021-06-24 17:06:17 +00:00
|
|
|
// SystemDiskUsage returns information about the daemon data disk usage.
|
|
|
|
// Callers must not mutate contents of the returned fields.
|
|
|
|
func (daemon *Daemon) SystemDiskUsage(ctx context.Context, opts system.DiskUsageOptions) (*types.DiskUsage, error) {
|
2021-08-04 16:42:50 +00:00
|
|
|
eg, ctx := errgroup.WithContext(ctx)
|
2016-08-23 23:24:15 +00:00
|
|
|
|
2021-06-23 13:26:54 +00:00
|
|
|
var containers []*types.Container
|
|
|
|
if opts.Containers {
|
2021-08-04 16:42:50 +00:00
|
|
|
eg.Go(func() error {
|
|
|
|
var err error
|
2022-11-29 15:46:19 +00:00
|
|
|
containers, err = daemon.containerDiskUsage(ctx)
|
2021-06-24 17:06:17 +00:00
|
|
|
return err
|
2021-06-23 13:26:54 +00:00
|
|
|
})
|
2016-08-23 23:24:15 +00:00
|
|
|
}
|
|
|
|
|
2021-06-23 13:26:54 +00:00
|
|
|
var (
|
|
|
|
images []*types.ImageSummary
|
|
|
|
layersSize int64
|
|
|
|
)
|
|
|
|
if opts.Images {
|
2021-08-04 16:42:50 +00:00
|
|
|
eg.Go(func() error {
|
|
|
|
var err error
|
2022-11-29 15:46:19 +00:00
|
|
|
images, err = daemon.imageDiskUsage(ctx)
|
2021-06-24 17:06:17 +00:00
|
|
|
return err
|
2021-08-04 16:42:50 +00:00
|
|
|
})
|
|
|
|
eg.Go(func() error {
|
|
|
|
var err error
|
2022-11-29 15:46:19 +00:00
|
|
|
layersSize, err = daemon.layerDiskUsage(ctx)
|
2021-08-04 16:42:50 +00:00
|
|
|
return err
|
2021-06-23 13:26:54 +00:00
|
|
|
})
|
2016-08-23 23:24:15 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 15:33:43 +00:00
|
|
|
var volumes []*volume.Volume
|
2021-06-23 13:26:54 +00:00
|
|
|
if opts.Volumes {
|
2021-08-04 16:42:50 +00:00
|
|
|
eg.Go(func() error {
|
|
|
|
var err error
|
2022-11-29 15:46:19 +00:00
|
|
|
volumes, err = daemon.localVolumesSize(ctx)
|
2021-08-04 16:42:50 +00:00
|
|
|
return err
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := eg.Wait(); err != nil {
|
|
|
|
return nil, err
|
2021-06-23 13:26:54 +00:00
|
|
|
}
|
2016-08-23 23:24:15 +00:00
|
|
|
return &types.DiskUsage{
|
2021-06-23 13:26:54 +00:00
|
|
|
LayersSize: layersSize,
|
|
|
|
Containers: containers,
|
|
|
|
Volumes: volumes,
|
|
|
|
Images: images,
|
2016-08-23 23:24:15 +00:00
|
|
|
}, nil
|
|
|
|
}
|