github.com/kim0/docker@v0.6.2-0.20161130212042-4addda3f07e7/daemon/disk_usage.go (about)

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