mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
add sizes in images and containers
This commit is contained in:
parent
908e4797a6
commit
a91b710961
8 changed files with 105 additions and 11 deletions
|
@ -11,6 +11,8 @@ type ApiImages struct {
|
|||
Tag string `json:",omitempty"`
|
||||
Id string
|
||||
Created int64 `json:",omitempty"`
|
||||
Size int64
|
||||
ParentSize int64
|
||||
}
|
||||
|
||||
type ApiInfo struct {
|
||||
|
@ -24,12 +26,14 @@ type ApiInfo struct {
|
|||
}
|
||||
|
||||
type ApiContainers struct {
|
||||
Id string
|
||||
Image string `json:",omitempty"`
|
||||
Command string `json:",omitempty"`
|
||||
Created int64 `json:",omitempty"`
|
||||
Status string `json:",omitempty"`
|
||||
Ports string `json:",omitempty"`
|
||||
Id string
|
||||
Image string `json:",omitempty"`
|
||||
Command string `json:",omitempty"`
|
||||
Created int64 `json:",omitempty"`
|
||||
Status string `json:",omitempty"`
|
||||
Ports string `json:",omitempty"`
|
||||
SizeRw int64
|
||||
SizeRootFs int64
|
||||
}
|
||||
|
||||
type ApiSearch struct {
|
||||
|
|
|
@ -1194,7 +1194,7 @@ func TestDeleteContainers(t *testing.T) {
|
|||
|
||||
func TestDeleteImages(t *testing.T) {
|
||||
//FIXME: Implement this test
|
||||
t.Skip("Test not implemented")
|
||||
t.Log("Test not implemented")
|
||||
}
|
||||
|
||||
// Mocked types for tests
|
||||
|
|
13
commands.go
13
commands.go
|
@ -728,12 +728,12 @@ func CmdImages(args ...string) error {
|
|||
|
||||
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
|
||||
if !*quiet {
|
||||
fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED")
|
||||
fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED\tSIZE")
|
||||
}
|
||||
|
||||
for _, out := range outs {
|
||||
if !*quiet {
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\n", out.Repository, out.Tag, out.Id, HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))))
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s (virtual %s)\n", out.Repository, out.Tag, out.Id, HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), HumanSize(out.Size), HumanSize(out.ParentSize))
|
||||
} else {
|
||||
fmt.Fprintln(w, out.Id)
|
||||
}
|
||||
|
@ -794,12 +794,17 @@ func CmdPs(args ...string) error {
|
|||
}
|
||||
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
|
||||
if !*quiet {
|
||||
fmt.Fprintln(w, "ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS")
|
||||
fmt.Fprintln(w, "ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tSIZE")
|
||||
}
|
||||
|
||||
for _, out := range outs {
|
||||
if !*quiet {
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", out.Id, out.Image, out.Command, out.Status, HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Ports)
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\t", out.Id, out.Image, out.Command, out.Status, HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Ports)
|
||||
if out.SizeRootFs > 0 {
|
||||
fmt.Fprintf(w, "%s (virtual %s)\n", HumanSize(out.SizeRw), HumanSize(out.SizeRootFs))
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s\n", HumanSize(out.SizeRw))
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintln(w, out.Id)
|
||||
}
|
||||
|
|
24
container.go
24
container.go
|
@ -11,6 +11,7 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -879,3 +880,26 @@ func validateId(id string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSize, return real size, virtual size
|
||||
func (container *Container) GetSize() (int64, int64) {
|
||||
var sizeRw, sizeRootfs int64
|
||||
|
||||
filepath.Walk(container.rwPath(), func(path string, fileInfo os.FileInfo, err error) error {
|
||||
if fileInfo != nil {
|
||||
sizeRw += fileInfo.Size()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
_, err := os.Stat(container.RootfsPath())
|
||||
if err == nil {
|
||||
filepath.Walk(container.RootfsPath(), func(path string, fileInfo os.FileInfo, err error) error {
|
||||
if fileInfo != nil {
|
||||
sizeRootfs += fileInfo.Size()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return sizeRw, sizeRootfs
|
||||
}
|
||||
|
|
9
graph.go
9
graph.go
|
@ -89,6 +89,15 @@ func (graph *Graph) Get(name string) (*Image, error) {
|
|||
if img.Id != id {
|
||||
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.Id)
|
||||
}
|
||||
if img.Size == 0 {
|
||||
root, err := img.root()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := StoreSize(img, root); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
img.graph = graph
|
||||
graph.lockSumMap.Lock()
|
||||
defer graph.lockSumMap.Unlock()
|
||||
|
|
24
image.go
24
image.go
|
@ -12,6 +12,7 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -27,6 +28,8 @@ type Image struct {
|
|||
Author string `json:"author,omitempty"`
|
||||
Config *Config `json:"config,omitempty"`
|
||||
graph *Graph
|
||||
Size int64
|
||||
ParentSize int64
|
||||
}
|
||||
|
||||
func LoadImage(root string) (*Image, error) {
|
||||
|
@ -93,6 +96,18 @@ func StoreImage(img *Image, layerData Archive, root string, store bool) error {
|
|||
if err := Untar(layerData, layer); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return StoreSize(img, root)
|
||||
}
|
||||
|
||||
func StoreSize(img *Image, root string) error {
|
||||
layer := layerPath(root)
|
||||
|
||||
filepath.Walk(layer, func(path string, fileInfo os.FileInfo, err error) error {
|
||||
img.Size += fileInfo.Size()
|
||||
return nil
|
||||
})
|
||||
|
||||
// Store the json ball
|
||||
jsonData, err := json.Marshal(img)
|
||||
if err != nil {
|
||||
|
@ -359,3 +374,12 @@ func (img *Image) Checksum() (string, error) {
|
|||
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
func (img *Image) getVirtualSize(size int64) int64 {
|
||||
parentImage, err := img.GetParent()
|
||||
if err != nil || parentImage == nil {
|
||||
return size
|
||||
}
|
||||
size += parentImage.Size
|
||||
return parentImage.getVirtualSize(size)
|
||||
}
|
||||
|
|
|
@ -164,6 +164,8 @@ func (srv *Server) Images(all, only_ids bool, filter string) ([]ApiImages, error
|
|||
out.Tag = tag
|
||||
out.Id = TruncateId(id)
|
||||
out.Created = image.Created.Unix()
|
||||
out.Size = image.Size
|
||||
out.ParentSize = image.getVirtualSize(0)
|
||||
} else {
|
||||
out.Id = image.ShortId()
|
||||
}
|
||||
|
@ -179,6 +181,8 @@ func (srv *Server) Images(all, only_ids bool, filter string) ([]ApiImages, error
|
|||
out.Tag = "<none>"
|
||||
out.Id = TruncateId(id)
|
||||
out.Created = image.Created.Unix()
|
||||
out.Size = image.Size
|
||||
out.ParentSize = image.getVirtualSize(0)
|
||||
} else {
|
||||
out.Id = image.ShortId()
|
||||
}
|
||||
|
@ -280,6 +284,7 @@ func (srv *Server) Containers(all, trunc_cmd, only_ids bool, n int, since, befor
|
|||
c.Created = container.Created.Unix()
|
||||
c.Status = container.State.String()
|
||||
c.Ports = container.NetworkSettings.PortMappingHuman()
|
||||
c.SizeRw, c.SizeRootFs = container.GetSize()
|
||||
}
|
||||
retContainers = append(retContainers, c)
|
||||
}
|
||||
|
|
23
utils.go
23
utils.go
|
@ -16,6 +16,7 @@ import (
|
|||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
_ "strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -133,6 +134,28 @@ func HumanDuration(d time.Duration) string {
|
|||
return fmt.Sprintf("%d years", d.Hours()/24/365)
|
||||
}
|
||||
|
||||
// HumanSize returns a human-readabla approximation of a size
|
||||
// (eg. "44K", "17M")
|
||||
func HumanSize(size int64) string {
|
||||
i := 0
|
||||
var sizef float64
|
||||
sizef = float64(size)
|
||||
units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||
for sizef > 1024.0 {
|
||||
sizef = sizef / 1024.0
|
||||
i++
|
||||
}
|
||||
return fmt.Sprintf("%.*f %s", i, sizef, units[i])
|
||||
// sprintf(buf, "%.*f %s", i, size, units[i]);
|
||||
// if size/1024/1024 > 1000 {
|
||||
// return strconv.FormatFloat((float64)(size/1024/1024), 'f', 2, 32) + "G"
|
||||
// }
|
||||
// if size/1024 > 1024 {
|
||||
// return strconv.FormatInt(size/1024/1024, 10) + "M"
|
||||
// }
|
||||
// return strconv.FormatInt(size/1024, 10) + "K"
|
||||
}
|
||||
|
||||
func Trunc(s string, maxlen int) string {
|
||||
if len(s) <= maxlen {
|
||||
return s
|
||||
|
|
Loading…
Reference in a new issue