disk_usage.go 3.7 KB

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