* go mod init; rm -rf vendor * tweak proto files and generation * go mod vendor * clean up build.go * protobuf literals in tests * downgrade gogo/protobuf
This commit is contained in:
9
vendor/github.com/prometheus/procfs/.travis.yml
generated
vendored
Normal file
9
vendor/github.com/prometheus/procfs/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
sudo: false
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.9.x
|
||||
- 1.x
|
||||
|
||||
go_import_path: github.com/prometheus/procfs
|
||||
18
vendor/github.com/prometheus/procfs/CONTRIBUTING.md
generated
vendored
Normal file
18
vendor/github.com/prometheus/procfs/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Contributing
|
||||
|
||||
Prometheus uses GitHub to manage reviews of pull requests.
|
||||
|
||||
* If you have a trivial fix or improvement, go ahead and create a pull request,
|
||||
addressing (with `@...`) the maintainer of this repository (see
|
||||
[MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request.
|
||||
|
||||
* If you plan to do something more involved, first discuss your ideas
|
||||
on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
|
||||
This will avoid unnecessary work and surely give you and us a good deal
|
||||
of inspiration.
|
||||
|
||||
* Relevant coding style guidelines are the [Go Code Review
|
||||
Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments)
|
||||
and the _Formatting and style_ section of Peter Bourgon's [Go: Best
|
||||
Practices for Production
|
||||
Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style).
|
||||
1
vendor/github.com/prometheus/procfs/MAINTAINERS.md
generated
vendored
Normal file
1
vendor/github.com/prometheus/procfs/MAINTAINERS.md
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* Tobias Schmidt <tobidt@gmail.com>
|
||||
18
vendor/github.com/prometheus/procfs/Makefile
generated
vendored
Normal file
18
vendor/github.com/prometheus/procfs/Makefile
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
ci: fmt lint test
|
||||
|
||||
fmt:
|
||||
! gofmt -l *.go | read nothing
|
||||
go vet
|
||||
|
||||
lint:
|
||||
go get github.com/golang/lint/golint
|
||||
golint *.go
|
||||
|
||||
test: sysfs/fixtures/.unpacked
|
||||
go test -v ./...
|
||||
|
||||
sysfs/fixtures/.unpacked: sysfs/fixtures.ttar
|
||||
./ttar -C sysfs -x -f sysfs/fixtures.ttar
|
||||
touch $@
|
||||
|
||||
.PHONY: fmt lint test ci
|
||||
7
vendor/github.com/prometheus/procfs/NOTICE
generated
vendored
Normal file
7
vendor/github.com/prometheus/procfs/NOTICE
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
procfs provides functions to retrieve system, kernel and process
|
||||
metrics from the pseudo-filesystem proc.
|
||||
|
||||
Copyright 2014-2015 The Prometheus Authors
|
||||
|
||||
This product includes software developed at
|
||||
SoundCloud Ltd. (http://soundcloud.com/).
|
||||
11
vendor/github.com/prometheus/procfs/README.md
generated
vendored
Normal file
11
vendor/github.com/prometheus/procfs/README.md
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# procfs
|
||||
|
||||
This procfs package provides functions to retrieve system, kernel and process
|
||||
metrics from the pseudo-filesystem proc.
|
||||
|
||||
*WARNING*: This package is a work in progress. Its API may still break in
|
||||
backwards-incompatible ways without warnings. Use it at your own risk.
|
||||
|
||||
[](https://godoc.org/github.com/prometheus/procfs)
|
||||
[](https://travis-ci.org/prometheus/procfs)
|
||||
[](https://goreportcard.com/report/github.com/prometheus/procfs)
|
||||
84
vendor/github.com/prometheus/procfs/bcache/bcache.go
generated
vendored
84
vendor/github.com/prometheus/procfs/bcache/bcache.go
generated
vendored
@@ -1,84 +0,0 @@
|
||||
// Copyright 2017 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package bcache provides access to statistics exposed by the bcache (Linux
|
||||
// block cache).
|
||||
package bcache
|
||||
|
||||
// Stats contains bcache runtime statistics, parsed from /sys/fs/bcache/.
|
||||
//
|
||||
// The names and meanings of each statistic were taken from bcache.txt and
|
||||
// files in drivers/md/bcache in the Linux kernel source. Counters are uint64
|
||||
// (in-kernel counters are mostly unsigned long).
|
||||
type Stats struct {
|
||||
// The name of the bcache used to source these statistics.
|
||||
Name string
|
||||
Bcache BcacheStats
|
||||
Bdevs []BdevStats
|
||||
Caches []CacheStats
|
||||
}
|
||||
|
||||
// BcacheStats contains statistics tied to a bcache ID.
|
||||
type BcacheStats struct {
|
||||
AverageKeySize uint64
|
||||
BtreeCacheSize uint64
|
||||
CacheAvailablePercent uint64
|
||||
Congested uint64
|
||||
RootUsagePercent uint64
|
||||
TreeDepth uint64
|
||||
Internal InternalStats
|
||||
FiveMin PeriodStats
|
||||
Total PeriodStats
|
||||
}
|
||||
|
||||
// BdevStats contains statistics for one backing device.
|
||||
type BdevStats struct {
|
||||
Name string
|
||||
DirtyData uint64
|
||||
FiveMin PeriodStats
|
||||
Total PeriodStats
|
||||
}
|
||||
|
||||
// CacheStats contains statistics for one cache device.
|
||||
type CacheStats struct {
|
||||
Name string
|
||||
IOErrors uint64
|
||||
MetadataWritten uint64
|
||||
Written uint64
|
||||
Priority PriorityStats
|
||||
}
|
||||
|
||||
// PriorityStats contains statistics from the priority_stats file.
|
||||
type PriorityStats struct {
|
||||
UnusedPercent uint64
|
||||
MetadataPercent uint64
|
||||
}
|
||||
|
||||
// InternalStats contains internal bcache statistics.
|
||||
type InternalStats struct {
|
||||
ActiveJournalEntries uint64
|
||||
BtreeNodes uint64
|
||||
BtreeReadAverageDurationNanoSeconds uint64
|
||||
CacheReadRaces uint64
|
||||
}
|
||||
|
||||
// PeriodStats contains statistics for a time period (5 min or total).
|
||||
type PeriodStats struct {
|
||||
Bypassed uint64
|
||||
CacheBypassHits uint64
|
||||
CacheBypassMisses uint64
|
||||
CacheHits uint64
|
||||
CacheMissCollisions uint64
|
||||
CacheMisses uint64
|
||||
CacheReadaheads uint64
|
||||
}
|
||||
330
vendor/github.com/prometheus/procfs/bcache/get.go
generated
vendored
330
vendor/github.com/prometheus/procfs/bcache/get.go
generated
vendored
@@ -1,330 +0,0 @@
|
||||
// Copyright 2017 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package bcache
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParsePseudoFloat parses the peculiar format produced by bcache's bch_hprint.
|
||||
func parsePseudoFloat(str string) (float64, error) {
|
||||
ss := strings.Split(str, ".")
|
||||
|
||||
intPart, err := strconv.ParseFloat(ss[0], 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if len(ss) == 1 {
|
||||
// Pure integers are fine.
|
||||
return intPart, nil
|
||||
}
|
||||
fracPart, err := strconv.ParseFloat(ss[1], 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// fracPart is a number between 0 and 1023 divided by 100; it is off
|
||||
// by a small amount. Unexpected bumps in time lines may occur because
|
||||
// for bch_hprint .1 != .10 and .10 > .9 (at least up to Linux
|
||||
// v4.12-rc3).
|
||||
|
||||
// Restore the proper order:
|
||||
fracPart = fracPart / 10.24
|
||||
return intPart + fracPart, nil
|
||||
}
|
||||
|
||||
// Dehumanize converts a human-readable byte slice into a uint64.
|
||||
func dehumanize(hbytes []byte) (uint64, error) {
|
||||
ll := len(hbytes)
|
||||
if ll == 0 {
|
||||
return 0, fmt.Errorf("zero-length reply")
|
||||
}
|
||||
lastByte := hbytes[ll-1]
|
||||
mul := float64(1)
|
||||
var (
|
||||
mant float64
|
||||
err error
|
||||
)
|
||||
// If lastByte is beyond the range of ASCII digits, it must be a
|
||||
// multiplier.
|
||||
if lastByte > 57 {
|
||||
// Remove multiplier from slice.
|
||||
hbytes = hbytes[:len(hbytes)-1]
|
||||
|
||||
const (
|
||||
_ = 1 << (10 * iota)
|
||||
KiB
|
||||
MiB
|
||||
GiB
|
||||
TiB
|
||||
PiB
|
||||
EiB
|
||||
ZiB
|
||||
YiB
|
||||
)
|
||||
|
||||
multipliers := map[rune]float64{
|
||||
// Source for conversion rules:
|
||||
// linux-kernel/drivers/md/bcache/util.c:bch_hprint()
|
||||
'k': KiB,
|
||||
'M': MiB,
|
||||
'G': GiB,
|
||||
'T': TiB,
|
||||
'P': PiB,
|
||||
'E': EiB,
|
||||
'Z': ZiB,
|
||||
'Y': YiB,
|
||||
}
|
||||
mul = multipliers[rune(lastByte)]
|
||||
mant, err = parsePseudoFloat(string(hbytes))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
// Not humanized by bch_hprint
|
||||
mant, err = strconv.ParseFloat(string(hbytes), 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
res := uint64(mant * mul)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
uuidPath string
|
||||
subDir string
|
||||
currentDir string
|
||||
err error
|
||||
}
|
||||
|
||||
func (p *parser) setSubDir(pathElements ...string) {
|
||||
p.subDir = path.Join(pathElements...)
|
||||
p.currentDir = path.Join(p.uuidPath, p.subDir)
|
||||
}
|
||||
|
||||
func (p *parser) readValue(fileName string) uint64 {
|
||||
if p.err != nil {
|
||||
return 0
|
||||
}
|
||||
path := path.Join(p.currentDir, fileName)
|
||||
byt, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
p.err = fmt.Errorf("failed to read: %s", path)
|
||||
return 0
|
||||
}
|
||||
// Remove trailing newline.
|
||||
byt = byt[:len(byt)-1]
|
||||
res, err := dehumanize(byt)
|
||||
p.err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// ParsePriorityStats parses lines from the priority_stats file.
|
||||
func parsePriorityStats(line string, ps *PriorityStats) error {
|
||||
var (
|
||||
value uint64
|
||||
err error
|
||||
)
|
||||
switch {
|
||||
case strings.HasPrefix(line, "Unused:"):
|
||||
fields := strings.Fields(line)
|
||||
rawValue := fields[len(fields)-1]
|
||||
valueStr := strings.TrimSuffix(rawValue, "%")
|
||||
value, err = strconv.ParseUint(valueStr, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ps.UnusedPercent = value
|
||||
case strings.HasPrefix(line, "Metadata:"):
|
||||
fields := strings.Fields(line)
|
||||
rawValue := fields[len(fields)-1]
|
||||
valueStr := strings.TrimSuffix(rawValue, "%")
|
||||
value, err = strconv.ParseUint(valueStr, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ps.MetadataPercent = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parser) getPriorityStats() PriorityStats {
|
||||
var res PriorityStats
|
||||
|
||||
if p.err != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
path := path.Join(p.currentDir, "priority_stats")
|
||||
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
p.err = fmt.Errorf("failed to read: %s", path)
|
||||
return res
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
err = parsePriorityStats(scanner.Text(), &res)
|
||||
if err != nil {
|
||||
p.err = fmt.Errorf("failed to parse: %s (%s)", path, err)
|
||||
return res
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
p.err = fmt.Errorf("failed to parse: %s (%s)", path, err)
|
||||
return res
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// GetStats collects from sysfs files data tied to one bcache ID.
|
||||
func GetStats(uuidPath string) (*Stats, error) {
|
||||
var bs Stats
|
||||
|
||||
par := parser{uuidPath: uuidPath}
|
||||
|
||||
// bcache stats
|
||||
|
||||
// dir <uuidPath>
|
||||
par.setSubDir("")
|
||||
bs.Bcache.AverageKeySize = par.readValue("average_key_size")
|
||||
bs.Bcache.BtreeCacheSize = par.readValue("btree_cache_size")
|
||||
bs.Bcache.CacheAvailablePercent = par.readValue("cache_available_percent")
|
||||
bs.Bcache.Congested = par.readValue("congested")
|
||||
bs.Bcache.RootUsagePercent = par.readValue("root_usage_percent")
|
||||
bs.Bcache.TreeDepth = par.readValue("tree_depth")
|
||||
|
||||
// bcache stats (internal)
|
||||
|
||||
// dir <uuidPath>/internal
|
||||
par.setSubDir("internal")
|
||||
bs.Bcache.Internal.ActiveJournalEntries = par.readValue("active_journal_entries")
|
||||
bs.Bcache.Internal.BtreeNodes = par.readValue("btree_nodes")
|
||||
bs.Bcache.Internal.BtreeReadAverageDurationNanoSeconds = par.readValue("btree_read_average_duration_us")
|
||||
bs.Bcache.Internal.CacheReadRaces = par.readValue("cache_read_races")
|
||||
|
||||
// bcache stats (period)
|
||||
|
||||
// dir <uuidPath>/stats_five_minute
|
||||
par.setSubDir("stats_five_minute")
|
||||
bs.Bcache.FiveMin.Bypassed = par.readValue("bypassed")
|
||||
bs.Bcache.FiveMin.CacheHits = par.readValue("cache_hits")
|
||||
|
||||
bs.Bcache.FiveMin.Bypassed = par.readValue("bypassed")
|
||||
bs.Bcache.FiveMin.CacheBypassHits = par.readValue("cache_bypass_hits")
|
||||
bs.Bcache.FiveMin.CacheBypassMisses = par.readValue("cache_bypass_misses")
|
||||
bs.Bcache.FiveMin.CacheHits = par.readValue("cache_hits")
|
||||
bs.Bcache.FiveMin.CacheMissCollisions = par.readValue("cache_miss_collisions")
|
||||
bs.Bcache.FiveMin.CacheMisses = par.readValue("cache_misses")
|
||||
bs.Bcache.FiveMin.CacheReadaheads = par.readValue("cache_readaheads")
|
||||
|
||||
// dir <uuidPath>/stats_total
|
||||
par.setSubDir("stats_total")
|
||||
bs.Bcache.Total.Bypassed = par.readValue("bypassed")
|
||||
bs.Bcache.Total.CacheHits = par.readValue("cache_hits")
|
||||
|
||||
bs.Bcache.Total.Bypassed = par.readValue("bypassed")
|
||||
bs.Bcache.Total.CacheBypassHits = par.readValue("cache_bypass_hits")
|
||||
bs.Bcache.Total.CacheBypassMisses = par.readValue("cache_bypass_misses")
|
||||
bs.Bcache.Total.CacheHits = par.readValue("cache_hits")
|
||||
bs.Bcache.Total.CacheMissCollisions = par.readValue("cache_miss_collisions")
|
||||
bs.Bcache.Total.CacheMisses = par.readValue("cache_misses")
|
||||
bs.Bcache.Total.CacheReadaheads = par.readValue("cache_readaheads")
|
||||
|
||||
if par.err != nil {
|
||||
return nil, par.err
|
||||
}
|
||||
|
||||
// bdev stats
|
||||
|
||||
reg := path.Join(uuidPath, "bdev[0-9]*")
|
||||
bdevDirs, err := filepath.Glob(reg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bs.Bdevs = make([]BdevStats, len(bdevDirs))
|
||||
|
||||
for ii, bdevDir := range bdevDirs {
|
||||
var bds = &bs.Bdevs[ii]
|
||||
|
||||
bds.Name = filepath.Base(bdevDir)
|
||||
|
||||
par.setSubDir(bds.Name)
|
||||
bds.DirtyData = par.readValue("dirty_data")
|
||||
|
||||
// dir <uuidPath>/<bds.Name>/stats_five_minute
|
||||
par.setSubDir(bds.Name, "stats_five_minute")
|
||||
bds.FiveMin.Bypassed = par.readValue("bypassed")
|
||||
bds.FiveMin.CacheBypassHits = par.readValue("cache_bypass_hits")
|
||||
bds.FiveMin.CacheBypassMisses = par.readValue("cache_bypass_misses")
|
||||
bds.FiveMin.CacheHits = par.readValue("cache_hits")
|
||||
bds.FiveMin.CacheMissCollisions = par.readValue("cache_miss_collisions")
|
||||
bds.FiveMin.CacheMisses = par.readValue("cache_misses")
|
||||
bds.FiveMin.CacheReadaheads = par.readValue("cache_readaheads")
|
||||
|
||||
// dir <uuidPath>/<bds.Name>/stats_total
|
||||
par.setSubDir("stats_total")
|
||||
bds.Total.Bypassed = par.readValue("bypassed")
|
||||
bds.Total.CacheBypassHits = par.readValue("cache_bypass_hits")
|
||||
bds.Total.CacheBypassMisses = par.readValue("cache_bypass_misses")
|
||||
bds.Total.CacheHits = par.readValue("cache_hits")
|
||||
bds.Total.CacheMissCollisions = par.readValue("cache_miss_collisions")
|
||||
bds.Total.CacheMisses = par.readValue("cache_misses")
|
||||
bds.Total.CacheReadaheads = par.readValue("cache_readaheads")
|
||||
}
|
||||
|
||||
if par.err != nil {
|
||||
return nil, par.err
|
||||
}
|
||||
|
||||
// cache stats
|
||||
|
||||
reg = path.Join(uuidPath, "cache[0-9]*")
|
||||
cacheDirs, err := filepath.Glob(reg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bs.Caches = make([]CacheStats, len(cacheDirs))
|
||||
|
||||
for ii, cacheDir := range cacheDirs {
|
||||
var cs = &bs.Caches[ii]
|
||||
cs.Name = filepath.Base(cacheDir)
|
||||
|
||||
// dir is <uuidPath>/<cs.Name>
|
||||
par.setSubDir(cs.Name)
|
||||
cs.IOErrors = par.readValue("io_errors")
|
||||
cs.MetadataWritten = par.readValue("metadata_written")
|
||||
cs.Written = par.readValue("written")
|
||||
|
||||
ps := par.getPriorityStats()
|
||||
cs.Priority = ps
|
||||
}
|
||||
|
||||
if par.err != nil {
|
||||
return nil, par.err
|
||||
}
|
||||
|
||||
return &bs, nil
|
||||
}
|
||||
16
vendor/github.com/prometheus/procfs/sysfs/doc.go
generated
vendored
16
vendor/github.com/prometheus/procfs/sysfs/doc.go
generated
vendored
@@ -1,16 +0,0 @@
|
||||
// Copyright 2017 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package sysfs provides functions to retrieve system and kernel metrics
|
||||
// from the pseudo-filesystem sys.
|
||||
package sysfs
|
||||
108
vendor/github.com/prometheus/procfs/sysfs/fs.go
generated
vendored
108
vendor/github.com/prometheus/procfs/sysfs/fs.go
generated
vendored
@@ -1,108 +0,0 @@
|
||||
// Copyright 2017 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sysfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/prometheus/procfs/bcache"
|
||||
"github.com/prometheus/procfs/xfs"
|
||||
)
|
||||
|
||||
// FS represents the pseudo-filesystem sys, which provides an interface to
|
||||
// kernel data structures.
|
||||
type FS string
|
||||
|
||||
// DefaultMountPoint is the common mount point of the sys filesystem.
|
||||
const DefaultMountPoint = "/sys"
|
||||
|
||||
// NewFS returns a new FS mounted under the given mountPoint. It will error
|
||||
// if the mount point can't be read.
|
||||
func NewFS(mountPoint string) (FS, error) {
|
||||
info, err := os.Stat(mountPoint)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not read %s: %s", mountPoint, err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return "", fmt.Errorf("mount point %s is not a directory", mountPoint)
|
||||
}
|
||||
|
||||
return FS(mountPoint), nil
|
||||
}
|
||||
|
||||
// Path returns the path of the given subsystem relative to the sys root.
|
||||
func (fs FS) Path(p ...string) string {
|
||||
return filepath.Join(append([]string{string(fs)}, p...)...)
|
||||
}
|
||||
|
||||
// XFSStats retrieves XFS filesystem runtime statistics for each mounted XFS
|
||||
// filesystem. Only available on kernel 4.4+. On older kernels, an empty
|
||||
// slice of *xfs.Stats will be returned.
|
||||
func (fs FS) XFSStats() ([]*xfs.Stats, error) {
|
||||
matches, err := filepath.Glob(fs.Path("fs/xfs/*/stats/stats"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stats := make([]*xfs.Stats, 0, len(matches))
|
||||
for _, m := range matches {
|
||||
f, err := os.Open(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// "*" used in glob above indicates the name of the filesystem.
|
||||
name := filepath.Base(filepath.Dir(filepath.Dir(m)))
|
||||
|
||||
// File must be closed after parsing, regardless of success or
|
||||
// failure. Defer is not used because of the loop.
|
||||
s, err := xfs.ParseStats(f)
|
||||
_ = f.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Name = name
|
||||
stats = append(stats, s)
|
||||
}
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// BcacheStats retrieves bcache runtime statistics for each bcache.
|
||||
func (fs FS) BcacheStats() ([]*bcache.Stats, error) {
|
||||
matches, err := filepath.Glob(fs.Path("fs/bcache/*-*"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stats := make([]*bcache.Stats, 0, len(matches))
|
||||
for _, uuidPath := range matches {
|
||||
// "*-*" in glob above indicates the name of the bcache.
|
||||
name := filepath.Base(uuidPath)
|
||||
|
||||
// stats
|
||||
s, err := bcache.GetStats(uuidPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Name = name
|
||||
stats = append(stats, s)
|
||||
}
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
264
vendor/github.com/prometheus/procfs/ttar
generated
vendored
Normal file
264
vendor/github.com/prometheus/procfs/ttar
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
#!/usr/bin/env bash
|
||||
# Purpose: plain text tar format
|
||||
# Limitations: - only suitable for text files, directories, and symlinks
|
||||
# - stores only filename, content, and mode
|
||||
# - not designed for untrusted input
|
||||
|
||||
# Note: must work with bash version 3.2 (macOS)
|
||||
|
||||
set -o errexit -o nounset
|
||||
|
||||
# Sanitize environment (for instance, standard sorting of glob matches)
|
||||
export LC_ALL=C
|
||||
|
||||
path=""
|
||||
CMD=""
|
||||
|
||||
function usage {
|
||||
bname=$(basename "$0")
|
||||
cat << USAGE
|
||||
Usage: $bname [-C <DIR>] -c -f <ARCHIVE> <FILE...> (create archive)
|
||||
$bname -t -f <ARCHIVE> (list archive contents)
|
||||
$bname [-C <DIR>] -x -f <ARCHIVE> (extract archive)
|
||||
|
||||
Options:
|
||||
-C <DIR> (change directory)
|
||||
|
||||
Example: Change to sysfs directory, create ttar file from fixtures directory
|
||||
$bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/
|
||||
USAGE
|
||||
exit "$1"
|
||||
}
|
||||
|
||||
function vecho {
|
||||
if [ "${VERBOSE:-}" == "yes" ]; then
|
||||
echo >&7 "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
function set_cmd {
|
||||
if [ -n "$CMD" ]; then
|
||||
echo "ERROR: more than one command given"
|
||||
echo
|
||||
usage 2
|
||||
fi
|
||||
CMD=$1
|
||||
}
|
||||
|
||||
while getopts :cf:htxvC: opt; do
|
||||
case $opt in
|
||||
c)
|
||||
set_cmd "create"
|
||||
;;
|
||||
f)
|
||||
ARCHIVE=$OPTARG
|
||||
;;
|
||||
h)
|
||||
usage 0
|
||||
;;
|
||||
t)
|
||||
set_cmd "list"
|
||||
;;
|
||||
x)
|
||||
set_cmd "extract"
|
||||
;;
|
||||
v)
|
||||
VERBOSE=yes
|
||||
exec 7>&1
|
||||
;;
|
||||
C)
|
||||
CDIR=$OPTARG
|
||||
;;
|
||||
*)
|
||||
echo >&2 "ERROR: invalid option -$OPTARG"
|
||||
echo
|
||||
usage 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Remove processed options from arguments
|
||||
shift $(( OPTIND - 1 ));
|
||||
|
||||
if [ "${CMD:-}" == "" ]; then
|
||||
echo >&2 "ERROR: no command given"
|
||||
echo
|
||||
usage 1
|
||||
elif [ "${ARCHIVE:-}" == "" ]; then
|
||||
echo >&2 "ERROR: no archive name given"
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
|
||||
function list {
|
||||
local path=""
|
||||
local size=0
|
||||
local line_no=0
|
||||
local ttar_file=$1
|
||||
if [ -n "${2:-}" ]; then
|
||||
echo >&2 "ERROR: too many arguments."
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
if [ ! -e "$ttar_file" ]; then
|
||||
echo >&2 "ERROR: file not found ($ttar_file)"
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
while read -r line; do
|
||||
line_no=$(( line_no + 1 ))
|
||||
if [ $size -gt 0 ]; then
|
||||
size=$(( size - 1 ))
|
||||
continue
|
||||
fi
|
||||
if [[ $line =~ ^Path:\ (.*)$ ]]; then
|
||||
path=${BASH_REMATCH[1]}
|
||||
elif [[ $line =~ ^Lines:\ (.*)$ ]]; then
|
||||
size=${BASH_REMATCH[1]}
|
||||
echo "$path"
|
||||
elif [[ $line =~ ^Directory:\ (.*)$ ]]; then
|
||||
path=${BASH_REMATCH[1]}
|
||||
echo "$path/"
|
||||
elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then
|
||||
echo "$path -> ${BASH_REMATCH[1]}"
|
||||
fi
|
||||
done < "$ttar_file"
|
||||
}
|
||||
|
||||
function extract {
|
||||
local path=""
|
||||
local size=0
|
||||
local line_no=0
|
||||
local ttar_file=$1
|
||||
if [ -n "${2:-}" ]; then
|
||||
echo >&2 "ERROR: too many arguments."
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
if [ ! -e "$ttar_file" ]; then
|
||||
echo >&2 "ERROR: file not found ($ttar_file)"
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
while IFS= read -r line; do
|
||||
line_no=$(( line_no + 1 ))
|
||||
if [ "$size" -gt 0 ]; then
|
||||
echo "$line" >> "$path"
|
||||
size=$(( size - 1 ))
|
||||
continue
|
||||
fi
|
||||
if [[ $line =~ ^Path:\ (.*)$ ]]; then
|
||||
path=${BASH_REMATCH[1]}
|
||||
if [ -e "$path" ] || [ -L "$path" ]; then
|
||||
rm "$path"
|
||||
fi
|
||||
elif [[ $line =~ ^Lines:\ (.*)$ ]]; then
|
||||
size=${BASH_REMATCH[1]}
|
||||
# Create file even if it is zero-length.
|
||||
touch "$path"
|
||||
vecho " $path"
|
||||
elif [[ $line =~ ^Mode:\ (.*)$ ]]; then
|
||||
mode=${BASH_REMATCH[1]}
|
||||
chmod "$mode" "$path"
|
||||
vecho "$mode"
|
||||
elif [[ $line =~ ^Directory:\ (.*)$ ]]; then
|
||||
path=${BASH_REMATCH[1]}
|
||||
mkdir -p "$path"
|
||||
vecho " $path/"
|
||||
elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then
|
||||
ln -s "${BASH_REMATCH[1]}" "$path"
|
||||
vecho " $path -> ${BASH_REMATCH[1]}"
|
||||
elif [[ $line =~ ^# ]]; then
|
||||
# Ignore comments between files
|
||||
continue
|
||||
else
|
||||
echo >&2 "ERROR: Unknown keyword on line $line_no: $line"
|
||||
exit 1
|
||||
fi
|
||||
done < "$ttar_file"
|
||||
}
|
||||
|
||||
function div {
|
||||
echo "# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" \
|
||||
"- - - - - -"
|
||||
}
|
||||
|
||||
function get_mode {
|
||||
local mfile=$1
|
||||
if [ -z "${STAT_OPTION:-}" ]; then
|
||||
if stat -c '%a' "$mfile" >/dev/null 2>&1; then
|
||||
STAT_OPTION='-c'
|
||||
STAT_FORMAT='%a'
|
||||
else
|
||||
STAT_OPTION='-f'
|
||||
STAT_FORMAT='%A'
|
||||
fi
|
||||
fi
|
||||
stat "${STAT_OPTION}" "${STAT_FORMAT}" "$mfile"
|
||||
}
|
||||
|
||||
function _create {
|
||||
shopt -s nullglob
|
||||
local mode
|
||||
while (( "$#" )); do
|
||||
file=$1
|
||||
if [ -L "$file" ]; then
|
||||
echo "Path: $file"
|
||||
symlinkTo=$(readlink "$file")
|
||||
echo "SymlinkTo: $symlinkTo"
|
||||
vecho " $file -> $symlinkTo"
|
||||
div
|
||||
elif [ -d "$file" ]; then
|
||||
# Strip trailing slash (if there is one)
|
||||
file=${file%/}
|
||||
echo "Directory: $file"
|
||||
mode=$(get_mode "$file")
|
||||
echo "Mode: $mode"
|
||||
vecho "$mode $file/"
|
||||
div
|
||||
# Find all files and dirs, including hidden/dot files
|
||||
for x in "$file/"{*,.[^.]*}; do
|
||||
_create "$x"
|
||||
done
|
||||
elif [ -f "$file" ]; then
|
||||
echo "Path: $file"
|
||||
lines=$(wc -l "$file"|awk '{print $1}')
|
||||
echo "Lines: $lines"
|
||||
cat "$file"
|
||||
mode=$(get_mode "$file")
|
||||
echo "Mode: $mode"
|
||||
vecho "$mode $file"
|
||||
div
|
||||
else
|
||||
echo >&2 "ERROR: file not found ($file in $(pwd))"
|
||||
exit 2
|
||||
fi
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
function create {
|
||||
ttar_file=$1
|
||||
shift
|
||||
if [ -z "${1:-}" ]; then
|
||||
echo >&2 "ERROR: missing arguments."
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
if [ -e "$ttar_file" ]; then
|
||||
rm "$ttar_file"
|
||||
fi
|
||||
exec > "$ttar_file"
|
||||
_create "$@"
|
||||
}
|
||||
|
||||
if [ -n "${CDIR:-}" ]; then
|
||||
if [[ "$ARCHIVE" != /* ]]; then
|
||||
# Relative path: preserve the archive's location before changing
|
||||
# directory
|
||||
ARCHIVE="$(pwd)/$ARCHIVE"
|
||||
fi
|
||||
cd "$CDIR"
|
||||
fi
|
||||
|
||||
"$CMD" "$ARCHIVE" "$@"
|
||||
Reference in New Issue
Block a user