add sizes in images and containers

This commit is contained in:
Victor Vieux 2013-05-13 15:10:26 +02:00
Родитель 908e4797a6
Коммит a91b710961
8 изменённых файлов: 105 добавлений и 11 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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)
}

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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()

Просмотреть файл

@ -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)
}

Просмотреть файл

@ -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