mirror of
https://github.com/containers/podman.git
synced 2025-10-15 02:06:42 +08:00
117 lines
2.3 KiB
Go
117 lines
2.3 KiB
Go
package stats
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// Storage represents /dev/sdXX/ctl.
|
|
type Storage struct {
|
|
Name string
|
|
Model string
|
|
Capacity int64
|
|
Partitions []*Partition
|
|
}
|
|
|
|
// Partition represents a part of /dev/sdXX/ctl.
|
|
type Partition struct {
|
|
Name string
|
|
Start uint64
|
|
End uint64
|
|
}
|
|
|
|
func ReadStorages(ctx context.Context, opts ...Option) ([]*Storage, error) {
|
|
cfg := newConfig(opts...)
|
|
sdctl := filepath.Join(cfg.rootdir, "/dev/sdctl")
|
|
f, err := os.Open(sdctl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
|
|
var a []*Storage
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
fields := bytes.Split(scanner.Bytes(), delim)
|
|
if len(fields) == 0 {
|
|
continue
|
|
}
|
|
exp := string(fields[0]) + "*"
|
|
if !strings.HasPrefix(exp, "sd") {
|
|
continue
|
|
}
|
|
dir := filepath.Join(cfg.rootdir, "/dev", exp)
|
|
m, err := filepath.Glob(dir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, dir := range m {
|
|
s, err := readStorage(dir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
a = append(a, s)
|
|
}
|
|
}
|
|
if err := scanner.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return a, nil
|
|
}
|
|
|
|
func readStorage(dir string) (*Storage, error) {
|
|
ctl := filepath.Join(dir, "ctl")
|
|
f, err := os.Open(ctl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
|
|
var s Storage
|
|
s.Name = filepath.Base(dir)
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
line := scanner.Bytes()
|
|
switch {
|
|
case bytes.HasPrefix(line, []byte("inquiry ")):
|
|
s.Model = string(bytes.TrimSpace(line[7:]))
|
|
case bytes.HasPrefix(line, []byte("geometry ")):
|
|
fields := bytes.Split(line, delim)
|
|
if len(fields) < 3 {
|
|
continue
|
|
}
|
|
var p intParser
|
|
sec := p.ParseInt64(string(fields[1]), 10)
|
|
size := p.ParseInt64(string(fields[2]), 10)
|
|
if err := p.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
s.Capacity = sec * size
|
|
case bytes.HasPrefix(line, []byte("part ")):
|
|
fields := bytes.Split(line, delim)
|
|
if len(fields) < 4 {
|
|
continue
|
|
}
|
|
var p intParser
|
|
start := p.ParseUint64(string(fields[2]), 10)
|
|
end := p.ParseUint64(string(fields[3]), 10)
|
|
if err := p.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
s.Partitions = append(s.Partitions, &Partition{
|
|
Name: string(fields[1]),
|
|
Start: start,
|
|
End: end,
|
|
})
|
|
}
|
|
}
|
|
if err := scanner.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return &s, nil
|
|
}
|