disk_usage.go 3.7 KB

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