disk_usage.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package daemon // import "github.com/docker/docker/daemon"
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/docker/docker/api/server/router/system"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/api/types/filters"
  8. "github.com/docker/docker/api/types/volume"
  9. "github.com/pkg/errors"
  10. "golang.org/x/sync/errgroup"
  11. )
  12. // containerDiskUsage obtains information about container data disk usage
  13. // and makes sure that only one calculation is performed at the same time.
  14. func (daemon *Daemon) containerDiskUsage(ctx context.Context) ([]*types.Container, error) {
  15. res, _, err := daemon.usageContainers.Do(ctx, struct{}{}, func(ctx context.Context) ([]*types.Container, error) {
  16. // Retrieve container list
  17. containers, err := daemon.Containers(ctx, &types.ContainerListOptions{
  18. Size: true,
  19. All: true,
  20. })
  21. if err != nil {
  22. return nil, fmt.Errorf("failed to retrieve container list: %v", err)
  23. }
  24. return containers, nil
  25. })
  26. return res, err
  27. }
  28. // imageDiskUsage obtains information about image data disk usage from image service
  29. // and makes sure that only one calculation is performed at the same time.
  30. func (daemon *Daemon) imageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) {
  31. imgs, _, err := daemon.usageImages.Do(ctx, struct{}{}, func(ctx context.Context) ([]*types.ImageSummary, error) {
  32. // Get all top images with extra attributes
  33. imgs, err := daemon.imageService.Images(ctx, types.ImageListOptions{
  34. Filters: filters.NewArgs(),
  35. SharedSize: true,
  36. ContainerCount: true,
  37. })
  38. if err != nil {
  39. return nil, errors.Wrap(err, "failed to retrieve image list")
  40. }
  41. return imgs, nil
  42. })
  43. return imgs, err
  44. }
  45. // localVolumesSize obtains information about volume disk usage from volumes service
  46. // and makes sure that only one size calculation is performed at the same time.
  47. func (daemon *Daemon) localVolumesSize(ctx context.Context) ([]*volume.Volume, error) {
  48. volumes, _, err := daemon.usageVolumes.Do(ctx, struct{}{}, func(ctx context.Context) ([]*volume.Volume, error) {
  49. volumes, err := daemon.volumes.LocalVolumesSize(ctx)
  50. if err != nil {
  51. return nil, err
  52. }
  53. return volumes, nil
  54. })
  55. return volumes, err
  56. }
  57. // layerDiskUsage obtains information about layer disk usage from image service
  58. // and makes sure that only one size calculation is performed at the same time.
  59. func (daemon *Daemon) layerDiskUsage(ctx context.Context) (int64, error) {
  60. usage, _, err := daemon.usageLayer.Do(ctx, struct{}{}, func(ctx context.Context) (int64, error) {
  61. usage, err := daemon.imageService.LayerDiskUsage(ctx)
  62. if err != nil {
  63. return 0, err
  64. }
  65. return usage, nil
  66. })
  67. return usage, err
  68. }
  69. // SystemDiskUsage returns information about the daemon data disk usage.
  70. // Callers must not mutate contents of the returned fields.
  71. func (daemon *Daemon) SystemDiskUsage(ctx context.Context, opts system.DiskUsageOptions) (*types.DiskUsage, error) {
  72. eg, ctx := errgroup.WithContext(ctx)
  73. var containers []*types.Container
  74. if opts.Containers {
  75. eg.Go(func() error {
  76. var err error
  77. containers, err = daemon.containerDiskUsage(ctx)
  78. return err
  79. })
  80. }
  81. var (
  82. images []*types.ImageSummary
  83. layersSize int64
  84. )
  85. if opts.Images {
  86. eg.Go(func() error {
  87. var err error
  88. images, err = daemon.imageDiskUsage(ctx)
  89. return err
  90. })
  91. eg.Go(func() error {
  92. var err error
  93. layersSize, err = daemon.layerDiskUsage(ctx)
  94. return err
  95. })
  96. }
  97. var volumes []*volume.Volume
  98. if opts.Volumes {
  99. eg.Go(func() error {
  100. var err error
  101. volumes, err = daemon.localVolumesSize(ctx)
  102. return err
  103. })
  104. }
  105. if err := eg.Wait(); err != nil {
  106. return nil, err
  107. }
  108. return &types.DiskUsage{
  109. LayersSize: layersSize,
  110. Containers: containers,
  111. Volumes: volumes,
  112. Images: images,
  113. }, nil
  114. }