Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

Commit

Permalink
Merge pull request #30 from felipecruz91/fix/return-size-as-number
Browse files Browse the repository at this point in the history
Return volume size as a numeric byte count
  • Loading branch information
felipecruz91 authored Aug 4, 2022
2 parents 5ecac3b + e569405 commit 1ead4b9
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 23 deletions.
21 changes: 13 additions & 8 deletions ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ function useDockerDesktopClient() {

type VolumeData = {
Driver: string;
Size: string;
Size: number;
SizeHuman: string;
Containers: string[];
};

Expand Down Expand Up @@ -152,7 +153,7 @@ export function App() {
}
label="Export volume"
onClick={handleExport(params.row)}
disabled={params.row.volumeSize === "0B"}
disabled={params.row.volumeSize === "0 B"}
/>,
<GridActionsCellItem
key={"action_import_" + params.row.id}
Expand All @@ -174,7 +175,7 @@ export function App() {
label="Save to image"
onClick={handleSave(params.row)}
showInMenu
disabled={params.row.volumeSize === "0B"}
disabled={params.row.volumeSize === "0 B"}
/>,
<GridActionsCellItem
key={"action_load_" + params.row.id}
Expand All @@ -197,7 +198,7 @@ export function App() {
label="Transfer to host"
onClick={handleTransfer(params.row)}
showInMenu
disabled={params.row.volumeSize === "0B"}
disabled={params.row.volumeSize === "0 B"}
/>,
<GridActionsCellItem
key={"action_empty_" + params.row.id}
Expand All @@ -209,7 +210,7 @@ export function App() {
label="Empty volume"
onClick={handleEmpty(params.row)}
showInMenu
disabled={params.row.volumeSize === "0B"}
disabled={params.row.volumeSize === "0 B"}
/>,
<GridActionsCellItem
key={"action_delete_" + params.row.id}
Expand Down Expand Up @@ -292,6 +293,7 @@ export function App() {
.then((results: Record<string, VolumeData>) => {
let rows = [];
let index = 0;
console.log(results)

for (const key in results) {
const value = results[key];
Expand All @@ -300,7 +302,7 @@ export function App() {
volumeDriver: value.Driver,
volumeName: key,
volumeContainers: value.Containers,
volumeSize: value.Size,
volumeSize: value.SizeHuman,
});
index++;
}
Expand Down Expand Up @@ -431,12 +433,15 @@ export function App() {
try {
ddClient.extension.vm.service
.get(`/volumes/${volumeName}/size`)
.then((size: string) => {
.then((res: any) => {
// e.g. {"Bytes":16000,"Human":"16.0 kB"}
const resJSON = JSON.stringify(res)
const sizeObj = JSON.parse(resJSON)
let rowsCopy = rows.slice(); // copy the array
const index = rowsCopy.findIndex(
(element) => element.volumeName === volumeName
);
rowsCopy[index].volumeSize = size;
rowsCopy[index].volumeSize = sizeObj.Human;

setRows(rowsCopy);

Expand Down
51 changes: 44 additions & 7 deletions vm/internal/backend/size.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@ package backend
import (
"bytes"
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/felipecruz91/vackup-docker-extension/internal/log"
"path/filepath"
"strconv"
"strings"
)

func GetVolumesSize(ctx context.Context, cli *client.Client, volumeName string) map[string]string {
type VolumeSize struct {
Bytes int64
Human string
}

func GetVolumesSize(ctx context.Context, cli *client.Client, volumeName string) map[string]VolumeSize {
resp, err := cli.ContainerCreate(ctx, &container.Config{
Tty: true,
Cmd: []string{"/bin/sh", "-c", "du -d 0 -h /var/lib/docker/volumes/" + volumeName},
Cmd: []string{"/bin/sh", "-c", "du -d 0 /var/lib/docker/volumes/" + volumeName},
Image: "docker.io/justincormack/nsenter1",
}, &container.HostConfig{
PidMode: "host",
Expand Down Expand Up @@ -51,9 +58,9 @@ func GetVolumesSize(ctx context.Context, cli *client.Client, volumeName string)
output := buf.String()

lines := strings.Split(strings.TrimSuffix(output, "\n"), "\n")
m := make(map[string]string)
m := make(map[string]VolumeSize)
for _, line := range lines {
s := strings.Split(line, "\t") // e.g. 41.5M /var/lib/docker/volumes/my-volume
s := strings.Split(line, "\t") // e.g. 924 /var/lib/docker/volumes/my-volume
if len(s) != 2 {
log.Warnf("skipping line: %s", line)
continue
Expand All @@ -62,18 +69,27 @@ func GetVolumesSize(ctx context.Context, cli *client.Client, volumeName string)
size := s[0]
path := strings.TrimSuffix(s[1], "\r")

sizeKB, err := strconv.ParseInt(size, 10, 64)
if err != nil {
log.Warn(err)
continue
}

if path == "/var/lib/docker/volumes/backingFsBlockDev" || path == "/var/lib/docker/volumes/metadata.db" {
// ignore "backingFsBlockDev" and "metadata.db" system volumes
continue
}

if size == "8.0K" {
if sizeKB == 8 {
// Apparently, inside the VM if a directory size is 8.0K, it is in fact "empty".
// Therefore, we set it to "0B" to indicate that the directory is empty.
size = "0B"
sizeKB = 0
}

m[filepath.Base(path)] = size
m[filepath.Base(path)] = VolumeSize{
Bytes: sizeKB * 1000,
Human: byteCountSI(sizeKB * 1000),
}
}

err = cli.ContainerRemove(ctx, resp.ID, types.ContainerRemoveOptions{})
Expand All @@ -83,3 +99,24 @@ func GetVolumesSize(ctx context.Context, cli *client.Client, volumeName string)

return m
}

// byteCountSI converts a size in bytes to a human-readable string in SI (decimal) format.
//
// e.g. 999 -> "999 B"
//
// e.g. 1000 -> "1.0 kB"
//
// e.g. 987,654,321 -> "987.7 MB"
func byteCountSI(b int64) string {
const unit = 1000
if b < unit {
return fmt.Sprintf("%d B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB",
float64(b)/float64(div), "kMGTPE"[exp])
}
3 changes: 2 additions & 1 deletion vm/internal/handler/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ func TestImportTarGzFile(t *testing.T) {
require.NoError(t, err)
require.Equal(t, http.StatusOK, rec.Code)
sizes := backend.GetVolumesSize(c.Request().Context(), cli, volume)
require.Regexp(t, ".*K", sizes[volume])
require.Equal(t, int64(16000), sizes[volume].Bytes)
require.Equal(t, "16.0 kB", sizes[volume].Human)
}
5 changes: 3 additions & 2 deletions vm/internal/handler/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func TestLoadImage(t *testing.T) {
require.NoError(t, err)
require.Equal(t, http.StatusOK, rec.Code)
sizes := backend.GetVolumesSize(c.Request().Context(), cli, volume)
t.Logf("Volume size after loading image into it: %s", sizes[volume])
require.Regexp(t, ".*K", sizes[volume])
t.Logf("Volume size after loading image into it: %+v", sizes[volume])
require.Equal(t, int64(16000), sizes[volume].Bytes)
require.Equal(t, "16.0 kB", sizes[volume].Human)
}
3 changes: 2 additions & 1 deletion vm/internal/handler/size_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,6 @@ func TestVolumeSize(t *testing.T) {
t.Log(size)

require.Equal(t, http.StatusOK, rec.Code)
require.Regexp(t, "\".*K\"\n", size)
require.Equal(t, `{"Bytes":16000,"Human":"16.0 kB"}
`, size)
}
9 changes: 6 additions & 3 deletions vm/internal/handler/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ type VolumesResponse struct {

type VolumeData struct {
Driver string
Size string
Size int64
SizeHuman string
Containers []string
}

Expand All @@ -41,11 +42,13 @@ func (h *Handler) Volumes(ctx echo.Context) error {
entry, ok := res.data[k]
if !ok {
res.data[k] = VolumeData{
Size: v,
Size: v.Bytes,
SizeHuman: v.Human,
}
continue
}
entry.Size = v
entry.Size = v.Bytes
entry.SizeHuman = v.Human
res.data[k] = entry
}
res.Unlock()
Expand Down
3 changes: 2 additions & 1 deletion vm/internal/handler/volumes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ func TestVolumes(t *testing.T) {
require.Equal(t, http.StatusOK, rec.Code)
require.Contains(t, m, volume)
require.Equal(t, "local", m[volume].Driver)
require.Equal(t, "0B", m[volume].Size)
require.Equal(t, int64(0), m[volume].Size)
require.Equal(t, "0 B", m[volume].SizeHuman)
require.Len(t, m[volume].Containers, 0)
}

Expand Down
4 changes: 4 additions & 0 deletions vm/internal/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ func Error(args ...interface{}) {
logger.Error(args...)
}

func Warn(args ...interface{}) {
logger.Warn(args...)
}

func Warnf(format string, args ...interface{}) {
logger.Warnf(format, args...)
}

0 comments on commit 1ead4b9

Please sign in to comment.