Merge pull request #976 from jimmidyson/net-stats-from-proc
Fix Devicemapper output parsing
This commit is contained in:
commit
060609f899
72
fs/fs.go
72
fs/fs.go
@ -19,7 +19,6 @@ package fs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
@ -337,6 +336,8 @@ func dockerStatusValue(status [][]string, target string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Devicemapper thin provisioning is detailed at
|
||||
// https://www.kernel.org/doc/Documentation/device-mapper/thin-provisioning.txt
|
||||
func dockerDMDevice(driverStatus string) (string, uint, uint, uint, error) {
|
||||
var config [][]string
|
||||
err := json.Unmarshal([]byte(driverStatus), &config)
|
||||
@ -348,46 +349,77 @@ func dockerDMDevice(driverStatus string) (string, uint, uint, uint, error) {
|
||||
return "", 0, 0, 0, fmt.Errorf("Could not get dm pool name")
|
||||
}
|
||||
|
||||
dmTable, err := exec.Command("dmsetup", "table", poolName).Output()
|
||||
out, err := exec.Command("dmsetup", "table", poolName).Output()
|
||||
if err != nil {
|
||||
return "", 0, 0, 0, err
|
||||
}
|
||||
|
||||
var (
|
||||
major, minor, dataBlkSize, bkt uint
|
||||
bkts string
|
||||
)
|
||||
|
||||
_, err = fmt.Fscanf(bytes.NewReader(dmTable),
|
||||
"%d %d %s %d:%d %d:%d %d %d %d %s",
|
||||
&bkt, &bkt, &bkts, &bkt, &bkt, &major, &minor, &dataBlkSize, &bkt, &bkt, &bkts)
|
||||
major, minor, dataBlkSize, err := parseDMTable(string(out))
|
||||
if err != nil {
|
||||
return "", 0, 0, 0, err
|
||||
}
|
||||
|
||||
return poolName, major, minor, dataBlkSize, nil
|
||||
}
|
||||
|
||||
func parseDMTable(dmTable string) (uint, uint, uint, error) {
|
||||
dmTable = strings.Replace(dmTable, ":", " ", -1)
|
||||
dmFields := strings.Fields(dmTable)
|
||||
|
||||
if len(dmFields) < 8 {
|
||||
return 0, 0, 0, fmt.Errorf("Invalid dmsetup status output: %s", dmTable)
|
||||
}
|
||||
|
||||
major, err := strconv.ParseUint(dmFields[5], 10, 32)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
minor, err := strconv.ParseUint(dmFields[6], 10, 32)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
dataBlkSize, err := strconv.ParseUint(dmFields[7], 10, 32)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
return uint(major), uint(minor), uint(dataBlkSize), nil
|
||||
}
|
||||
|
||||
func getDMStats(poolName string, dataBlkSize uint) (uint64, uint64, uint64, error) {
|
||||
dmStatus, err := exec.Command("dmsetup", "status", poolName).Output()
|
||||
out, err := exec.Command("dmsetup", "status", poolName).Output()
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
var (
|
||||
total, used, bkt uint64
|
||||
bkts string
|
||||
)
|
||||
|
||||
_, err = fmt.Fscanf(bytes.NewReader(dmStatus),
|
||||
"%d %d %s %d %d/%d %d/%d %s %s %s %s",
|
||||
&bkt, &bkt, &bkts, &bkt, &bkt, &bkt, &used, &total, &bkts, &bkts, &bkts, &bkts)
|
||||
used, total, err := parseDMStatus(string(out))
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
total *= 512 * uint64(dataBlkSize)
|
||||
used *= 512 * uint64(dataBlkSize)
|
||||
total *= 512 * uint64(dataBlkSize)
|
||||
free := total - used
|
||||
|
||||
return total, free, free, nil
|
||||
}
|
||||
|
||||
func parseDMStatus(dmStatus string) (uint64, uint64, error) {
|
||||
dmStatus = strings.Replace(dmStatus, "/", " ", -1)
|
||||
dmFields := strings.Fields(dmStatus)
|
||||
|
||||
if len(dmFields) < 8 {
|
||||
return 0, 0, fmt.Errorf("Invalid dmsetup status output: %s", dmStatus)
|
||||
}
|
||||
|
||||
used, err := strconv.ParseUint(dmFields[6], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
total, err := strconv.ParseUint(dmFields[7], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return used, total, nil
|
||||
}
|
||||
|
@ -100,3 +100,59 @@ func TestDirUsage(t *testing.T) {
|
||||
as.NoError(err)
|
||||
as.True(expectedSize <= size, "expected dir size to be at-least %d; got size: %d", expectedSize, size)
|
||||
}
|
||||
|
||||
var dmStatusTests = []struct {
|
||||
dmStatus string
|
||||
used uint64
|
||||
total uint64
|
||||
errExpected bool
|
||||
}{
|
||||
{`0 409534464 thin-pool 64085 3705/4161600 88106/3199488 - rw no_discard_passdown queue_if_no_space -`, 88106, 3199488, false},
|
||||
{`0 209715200 thin-pool 707 1215/524288 30282/1638400 - rw discard_passdown`, 30282, 1638400, false},
|
||||
{`Invalid status line`, 0, 0, false},
|
||||
}
|
||||
|
||||
func TestParseDMStatus(t *testing.T) {
|
||||
for _, tt := range dmStatusTests {
|
||||
used, total, err := parseDMStatus(tt.dmStatus)
|
||||
if tt.errExpected && err != nil {
|
||||
t.Errorf("parseDMStatus(%q) expected error", tt.dmStatus)
|
||||
}
|
||||
if used != tt.used {
|
||||
t.Errorf("parseDMStatus(%q) wrong used value => %q, want %q", tt.dmStatus, used, tt.used)
|
||||
}
|
||||
if total != tt.total {
|
||||
t.Errorf("parseDMStatus(%q) wrong total value => %q, want %q", tt.dmStatus, total, tt.total)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dmTableTests = []struct {
|
||||
dmTable string
|
||||
major uint
|
||||
minor uint
|
||||
dataBlkSize uint
|
||||
errExpected bool
|
||||
}{
|
||||
{`0 409534464 thin-pool 253:6 253:7 128 32768 1 skip_block_zeroing`, 253, 7, 128, false},
|
||||
{`0 409534464 thin-pool 253:6 258:9 512 32768 1 skip_block_zeroing otherstuff`, 258, 9, 512, false},
|
||||
{`Invalid status line`, 0, 0, 0, false},
|
||||
}
|
||||
|
||||
func TestParseDMTable(t *testing.T) {
|
||||
for _, tt := range dmTableTests {
|
||||
major, minor, dataBlkSize, err := parseDMTable(tt.dmTable)
|
||||
if tt.errExpected && err != nil {
|
||||
t.Errorf("parseDMTable(%q) expected error", tt.dmTable)
|
||||
}
|
||||
if major != tt.major {
|
||||
t.Errorf("parseDMTable(%q) wrong major value => %q, want %q", tt.dmTable, major, tt.major)
|
||||
}
|
||||
if minor != tt.minor {
|
||||
t.Errorf("parseDMTable(%q) wrong minor value => %q, want %q", tt.dmTable, minor, tt.minor)
|
||||
}
|
||||
if dataBlkSize != tt.dataBlkSize {
|
||||
t.Errorf("parseDMTable(%q) wrong dataBlkSize value => %q, want %q", tt.dmTable, dataBlkSize, tt.dataBlkSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user