disk_usage.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package daemon
  2. import (
  3. "fmt"
  4. "github.com/Sirupsen/logrus"
  5. "github.com/docker/distribution/digest"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/api/types/filters"
  8. "github.com/docker/docker/layer"
  9. "github.com/docker/docker/pkg/directory"
  10. "github.com/docker/docker/volume"
  11. )
  12. func (daemon *Daemon) getLayerRefs() map[layer.ChainID]int {
  13. tmpImages := daemon.imageStore.Map()
  14. layerRefs := map[layer.ChainID]int{}
  15. for id, img := range tmpImages {
  16. dgst := digest.Digest(id)
  17. if len(daemon.referenceStore.References(dgst)) == 0 && len(daemon.imageStore.Children(id)) != 0 {
  18. continue
  19. }
  20. rootFS := *img.RootFS
  21. rootFS.DiffIDs = nil
  22. for _, id := range img.RootFS.DiffIDs {
  23. rootFS.Append(id)
  24. chid := rootFS.ChainID()
  25. layerRefs[chid]++
  26. }
  27. }
  28. return layerRefs
  29. }
  30. // SystemDiskUsage returns information about the daemon data disk usage
  31. func (daemon *Daemon) SystemDiskUsage() (*types.DiskUsage, error) {
  32. // Retrieve container list
  33. allContainers, err := daemon.Containers(&types.ContainerListOptions{
  34. Size: true,
  35. All: true,
  36. })
  37. if err != nil {
  38. return nil, fmt.Errorf("failed to retrieve container list: %v", err)
  39. }
  40. // Get all top images with extra attributes
  41. allImages, err := daemon.Images(filters.NewArgs(), false, true)
  42. if err != nil {
  43. return nil, fmt.Errorf("failed to retrieve image list: %v", err)
  44. }
  45. // Get all local volumes
  46. allVolumes := []*types.Volume{}
  47. getLocalVols := func(v volume.Volume) error {
  48. name := v.Name()
  49. refs := daemon.volumes.Refs(v)
  50. tv := volumeToAPIType(v)
  51. sz, err := directory.Size(v.Path())
  52. if err != nil {
  53. logrus.Warnf("failed to determine size of volume %v", name)
  54. sz = -1
  55. }
  56. tv.UsageData = &types.VolumeUsageData{Size: sz, RefCount: int64(len(refs))}
  57. allVolumes = append(allVolumes, tv)
  58. return nil
  59. }
  60. err = daemon.traverseLocalVolumes(getLocalVols)
  61. if err != nil {
  62. return nil, err
  63. }
  64. // Get total layers size on disk
  65. layerRefs := daemon.getLayerRefs()
  66. allLayers := daemon.layerStore.Map()
  67. var allLayersSize int64
  68. for _, l := range allLayers {
  69. size, err := l.DiffSize()
  70. if err == nil {
  71. if _, ok := layerRefs[l.ChainID()]; ok {
  72. allLayersSize += size
  73. } else {
  74. logrus.Warnf("found leaked image layer %v", l.ChainID())
  75. }
  76. } else {
  77. logrus.Warnf("failed to get diff size for layer %v", l.ChainID())
  78. }
  79. }
  80. return &types.DiskUsage{
  81. LayersSize: allLayersSize,
  82. Containers: allContainers,
  83. Volumes: allVolumes,
  84. Images: allImages,
  85. }, nil
  86. }