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"`
|
Tag string `json:",omitempty"`
|
||||||
Id string
|
Id string
|
||||||
Created int64 `json:",omitempty"`
|
Created int64 `json:",omitempty"`
|
||||||
|
Size int64
|
||||||
|
ParentSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiInfo struct {
|
type ApiInfo struct {
|
||||||
|
@ -24,12 +26,14 @@ type ApiInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiContainers struct {
|
type ApiContainers struct {
|
||||||
Id string
|
Id string
|
||||||
Image string `json:",omitempty"`
|
Image string `json:",omitempty"`
|
||||||
Command string `json:",omitempty"`
|
Command string `json:",omitempty"`
|
||||||
Created int64 `json:",omitempty"`
|
Created int64 `json:",omitempty"`
|
||||||
Status string `json:",omitempty"`
|
Status string `json:",omitempty"`
|
||||||
Ports string `json:",omitempty"`
|
Ports string `json:",omitempty"`
|
||||||
|
SizeRw int64
|
||||||
|
SizeRootFs int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiSearch struct {
|
type ApiSearch struct {
|
||||||
|
|
|
@ -1194,7 +1194,7 @@ func TestDeleteContainers(t *testing.T) {
|
||||||
|
|
||||||
func TestDeleteImages(t *testing.T) {
|
func TestDeleteImages(t *testing.T) {
|
||||||
//FIXME: Implement this test
|
//FIXME: Implement this test
|
||||||
t.Skip("Test not implemented")
|
t.Log("Test not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mocked types for tests
|
// 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)
|
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
|
||||||
if !*quiet {
|
if !*quiet {
|
||||||
fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED")
|
fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED\tSIZE")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, out := range outs {
|
for _, out := range outs {
|
||||||
if !*quiet {
|
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 {
|
} else {
|
||||||
fmt.Fprintln(w, out.Id)
|
fmt.Fprintln(w, out.Id)
|
||||||
}
|
}
|
||||||
|
@ -794,12 +794,17 @@ func CmdPs(args ...string) error {
|
||||||
}
|
}
|
||||||
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
|
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
|
||||||
if !*quiet {
|
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 {
|
for _, out := range outs {
|
||||||
if !*quiet {
|
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 {
|
} else {
|
||||||
fmt.Fprintln(w, out.Id)
|
fmt.Fprintln(w, out.Id)
|
||||||
}
|
}
|
||||||
|
|
24
container.go
24
container.go
|
@ -11,6 +11,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -879,3 +880,26 @@ func validateId(id string) error {
|
||||||
}
|
}
|
||||||
return nil
|
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 {
|
if img.Id != id {
|
||||||
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.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
|
img.graph = graph
|
||||||
graph.lockSumMap.Lock()
|
graph.lockSumMap.Lock()
|
||||||
defer graph.lockSumMap.Unlock()
|
defer graph.lockSumMap.Unlock()
|
||||||
|
|
24
image.go
24
image.go
|
@ -12,6 +12,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -27,6 +28,8 @@ type Image struct {
|
||||||
Author string `json:"author,omitempty"`
|
Author string `json:"author,omitempty"`
|
||||||
Config *Config `json:"config,omitempty"`
|
Config *Config `json:"config,omitempty"`
|
||||||
graph *Graph
|
graph *Graph
|
||||||
|
Size int64
|
||||||
|
ParentSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadImage(root string) (*Image, error) {
|
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 {
|
if err := Untar(layerData, layer); err != nil {
|
||||||
return err
|
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
|
// Store the json ball
|
||||||
jsonData, err := json.Marshal(img)
|
jsonData, err := json.Marshal(img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -359,3 +374,12 @@ func (img *Image) Checksum() (string, error) {
|
||||||
|
|
||||||
return hash, nil
|
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.Tag = tag
|
||||||
out.Id = TruncateId(id)
|
out.Id = TruncateId(id)
|
||||||
out.Created = image.Created.Unix()
|
out.Created = image.Created.Unix()
|
||||||
|
out.Size = image.Size
|
||||||
|
out.ParentSize = image.getVirtualSize(0)
|
||||||
} else {
|
} else {
|
||||||
out.Id = image.ShortId()
|
out.Id = image.ShortId()
|
||||||
}
|
}
|
||||||
|
@ -179,6 +181,8 @@ func (srv *Server) Images(all, only_ids bool, filter string) ([]ApiImages, error
|
||||||
out.Tag = "<none>"
|
out.Tag = "<none>"
|
||||||
out.Id = TruncateId(id)
|
out.Id = TruncateId(id)
|
||||||
out.Created = image.Created.Unix()
|
out.Created = image.Created.Unix()
|
||||||
|
out.Size = image.Size
|
||||||
|
out.ParentSize = image.getVirtualSize(0)
|
||||||
} else {
|
} else {
|
||||||
out.Id = image.ShortId()
|
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.Created = container.Created.Unix()
|
||||||
c.Status = container.State.String()
|
c.Status = container.State.String()
|
||||||
c.Ports = container.NetworkSettings.PortMappingHuman()
|
c.Ports = container.NetworkSettings.PortMappingHuman()
|
||||||
|
c.SizeRw, c.SizeRootFs = container.GetSize()
|
||||||
}
|
}
|
||||||
retContainers = append(retContainers, c)
|
retContainers = append(retContainers, c)
|
||||||
}
|
}
|
||||||
|
|
23
utils.go
23
utils.go
|
@ -16,6 +16,7 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
_ "strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -133,6 +134,28 @@ func HumanDuration(d time.Duration) string {
|
||||||
return fmt.Sprintf("%d years", d.Hours()/24/365)
|
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 {
|
func Trunc(s string, maxlen int) string {
|
||||||
if len(s) <= maxlen {
|
if len(s) <= maxlen {
|
||||||
return s
|
return s
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue