diff --git a/disk/disk_aix_nocgo.go b/disk/disk_aix_nocgo.go index 4fe1258c8a..ca25be50cd 100644 --- a/disk/disk_aix_nocgo.go +++ b/disk/disk_aix_nocgo.go @@ -5,6 +5,7 @@ package disk import ( "context" + "fmt" "regexp" "strconv" "strings" @@ -26,8 +27,46 @@ var ( } ) -func IOCountersWithContext(_ context.Context, _ ...string) (map[string]IOCountersStat, error) { - return nil, common.ErrNotImplementedError +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { + out, err := invoke.CommandWithContext(ctx, "iostat", "-d") + if err != nil { + return nil, err + } + + ret := make(map[string]IOCountersStat) + lines := strings.Split(string(out), "\n") + for _, line := range lines { + fields := strings.Fields(line) + if len(fields) < 6 { + continue + } + // Skip the header line + if fields[0] == "Disks:" { + continue + } + + name := fields[0] + if len(names) > 0 && !common.StringsHas(names, name) { + continue + } + + kbRead, err := strconv.ParseUint(fields[4], 10, 64) + if err != nil { + continue + } + kbWritten, err := strconv.ParseUint(fields[5], 10, 64) + if err != nil { + continue + } + + ret[name] = IOCountersStat{ + Name: name, + ReadBytes: kbRead * 1024, + WriteBytes: kbWritten * 1024, + } + } + + return ret, nil } func PartitionsWithContext(ctx context.Context, _ bool) ([]PartitionStat, error) { @@ -94,85 +133,117 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) { return nil, err } - ret := &UsageStat{} - blocksize := uint64(512) lines := strings.Split(string(out), "\n") if len(lines) < 2 { - return &UsageStat{}, common.ErrNotImplementedError + return nil, common.ErrNotImplementedError } hf := strings.Fields(strings.ReplaceAll(lines[0], "Mounted on", "Path")) // headers + + // Find the Path column index once before the loop. + pathIdx := -1 + for i, header := range hf { + if header == "Path" { + pathIdx = i + break + } + } + for line := 1; line < len(lines); line++ { fs := strings.Fields(lines[line]) // values + if len(fs) < len(hf) { + continue + } + + if pathIdx < 0 || fs[pathIdx] != path { + continue + } + + ret := &UsageStat{} for i, header := range hf { - // We're done in any of these use cases if i >= len(fs) { break } switch header { - case `Filesystem`: - // This is not a valid fs for us to parse - if fs[i] == "/proc" || fs[i] == "/ahafs" || fs[i] != path { - break - } - - ret.Fstype, err = GetMountFSTypeWithContext(ctx, fs[i]) - if err != nil { - return nil, err - } case `Path`: ret.Path = fs[i] case `512-blocks`: + if fs[i] == "-" { + continue + } total, err := strconv.ParseUint(fs[i], 10, 64) - ret.Total = total * blocksize if err != nil { return nil, err } + ret.Total = total * blocksize case `Used`: - ret.Used, err = strconv.ParseUint(fs[i], 10, 64) + if fs[i] == "-" { + continue + } + used, err := strconv.ParseUint(fs[i], 10, 64) if err != nil { return nil, err } + ret.Used = used * blocksize case `Free`: - ret.Free, err = strconv.ParseUint(fs[i], 10, 64) + if fs[i] == "-" { + continue + } + free, err := strconv.ParseUint(fs[i], 10, 64) if err != nil { return nil, err } + ret.Free = free * blocksize case `%Used`: + if fs[i] == "-" { + continue + } val, err := strconv.ParseInt(strings.ReplaceAll(fs[i], "%", ""), 10, 32) if err != nil { return nil, err } - ret.UsedPercent = float64(val) / float64(100) + ret.UsedPercent = float64(val) case `Ifree`: + if fs[i] == "-" { + continue + } ret.InodesFree, err = strconv.ParseUint(fs[i], 10, 64) if err != nil { return nil, err } case `Iused`: + if fs[i] == "-" { + continue + } ret.InodesUsed, err = strconv.ParseUint(fs[i], 10, 64) if err != nil { return nil, err } case `%Iused`: + if fs[i] == "-" { + continue + } val, err := strconv.ParseInt(strings.ReplaceAll(fs[i], "%", ""), 10, 32) if err != nil { return nil, err } - ret.InodesUsedPercent = float64(val) / float64(100) + ret.InodesUsedPercent = float64(val) } } - // Calculated value, since it isn't returned by the command ret.InodesTotal = ret.InodesUsed + ret.InodesFree - // Valid Usage data, so append it + var statfs unix.Statfs_t + if err := unix.Statfs(path, &statfs); err == nil { + ret.Fstype = getFsType(statfs) + } + return ret, nil } - return ret, nil + return nil, fmt.Errorf("mountpoint %s not found", path) } func GetMountFSTypeWithContext(ctx context.Context, mp string) (string, error) {