mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
rebase: update K8s packages to v0.32.1
Update K8s packages in go.mod to v0.32.1 Signed-off-by: Praveen M <m.praveen@ibm.com>
This commit is contained in:
360
vendor/github.com/mistifyio/go-zfs/utils.go
generated
vendored
Normal file
360
vendor/github.com/mistifyio/go-zfs/utils.go
generated
vendored
Normal file
@ -0,0 +1,360 @@
|
||||
package zfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type command struct {
|
||||
Command string
|
||||
Stdin io.Reader
|
||||
Stdout io.Writer
|
||||
}
|
||||
|
||||
func (c *command) Run(arg ...string) ([][]string, error) {
|
||||
|
||||
cmd := exec.Command(c.Command, arg...)
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
if c.Stdout == nil {
|
||||
cmd.Stdout = &stdout
|
||||
} else {
|
||||
cmd.Stdout = c.Stdout
|
||||
}
|
||||
|
||||
if c.Stdin != nil {
|
||||
cmd.Stdin = c.Stdin
|
||||
|
||||
}
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
id := uuid.New().String()
|
||||
joinedArgs := strings.Join(cmd.Args, " ")
|
||||
|
||||
logger.Log([]string{"ID:" + id, "START", joinedArgs})
|
||||
err := cmd.Run()
|
||||
logger.Log([]string{"ID:" + id, "FINISH"})
|
||||
|
||||
if err != nil {
|
||||
return nil, &Error{
|
||||
Err: err,
|
||||
Debug: strings.Join([]string{cmd.Path, joinedArgs[1:]}, " "),
|
||||
Stderr: stderr.String(),
|
||||
}
|
||||
}
|
||||
|
||||
// assume if you passed in something for stdout, that you know what to do with it
|
||||
if c.Stdout != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
lines := strings.Split(stdout.String(), "\n")
|
||||
|
||||
//last line is always blank
|
||||
lines = lines[0 : len(lines)-1]
|
||||
output := make([][]string, len(lines))
|
||||
|
||||
for i, l := range lines {
|
||||
output[i] = strings.Fields(l)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func setString(field *string, value string) {
|
||||
v := ""
|
||||
if value != "-" {
|
||||
v = value
|
||||
}
|
||||
*field = v
|
||||
}
|
||||
|
||||
func setUint(field *uint64, value string) error {
|
||||
var v uint64
|
||||
if value != "-" {
|
||||
var err error
|
||||
v, err = strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*field = v
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *Dataset) parseLine(line []string) error {
|
||||
var err error
|
||||
|
||||
if len(line) != len(dsPropList) {
|
||||
return errors.New("Output does not match what is expected on this platform")
|
||||
}
|
||||
setString(&ds.Name, line[0])
|
||||
setString(&ds.Origin, line[1])
|
||||
|
||||
if err = setUint(&ds.Used, line[2]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = setUint(&ds.Avail, line[3]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
setString(&ds.Mountpoint, line[4])
|
||||
setString(&ds.Compression, line[5])
|
||||
setString(&ds.Type, line[6])
|
||||
|
||||
if err = setUint(&ds.Volsize, line[7]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = setUint(&ds.Quota, line[8]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = setUint(&ds.Referenced, line[9]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if runtime.GOOS == "solaris" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = setUint(&ds.Written, line[10]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = setUint(&ds.Logicalused, line[11]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = setUint(&ds.Usedbydataset, line[12]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
* from zfs diff`s escape function:
|
||||
*
|
||||
* Prints a file name out a character at a time. If the character is
|
||||
* not in the range of what we consider "printable" ASCII, display it
|
||||
* as an escaped 3-digit octal value. ASCII values less than a space
|
||||
* are all control characters and we declare the upper end as the
|
||||
* DELete character. This also is the last 7-bit ASCII character.
|
||||
* We choose to treat all 8-bit ASCII as not printable for this
|
||||
* application.
|
||||
*/
|
||||
func unescapeFilepath(path string) (string, error) {
|
||||
buf := make([]byte, 0, len(path))
|
||||
llen := len(path)
|
||||
for i := 0; i < llen; {
|
||||
if path[i] == '\\' {
|
||||
if llen < i+4 {
|
||||
return "", fmt.Errorf("Invalid octal code: too short")
|
||||
}
|
||||
octalCode := path[(i + 1):(i + 4)]
|
||||
val, err := strconv.ParseUint(octalCode, 8, 8)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Invalid octal code: %v", err)
|
||||
}
|
||||
buf = append(buf, byte(val))
|
||||
i += 4
|
||||
} else {
|
||||
buf = append(buf, path[i])
|
||||
i++
|
||||
}
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
var changeTypeMap = map[string]ChangeType{
|
||||
"-": Removed,
|
||||
"+": Created,
|
||||
"M": Modified,
|
||||
"R": Renamed,
|
||||
}
|
||||
var inodeTypeMap = map[string]InodeType{
|
||||
"B": BlockDevice,
|
||||
"C": CharacterDevice,
|
||||
"/": Directory,
|
||||
">": Door,
|
||||
"|": NamedPipe,
|
||||
"@": SymbolicLink,
|
||||
"P": EventPort,
|
||||
"=": Socket,
|
||||
"F": File,
|
||||
}
|
||||
|
||||
// matches (+1) or (-1)
|
||||
var referenceCountRegex = regexp.MustCompile("\\(([+-]\\d+?)\\)")
|
||||
|
||||
func parseReferenceCount(field string) (int, error) {
|
||||
matches := referenceCountRegex.FindStringSubmatch(field)
|
||||
if matches == nil {
|
||||
return 0, fmt.Errorf("Regexp does not match")
|
||||
}
|
||||
return strconv.Atoi(matches[1])
|
||||
}
|
||||
|
||||
func parseInodeChange(line []string) (*InodeChange, error) {
|
||||
llen := len(line)
|
||||
if llen < 1 {
|
||||
return nil, fmt.Errorf("Empty line passed")
|
||||
}
|
||||
|
||||
changeType := changeTypeMap[line[0]]
|
||||
if changeType == 0 {
|
||||
return nil, fmt.Errorf("Unknown change type '%s'", line[0])
|
||||
}
|
||||
|
||||
switch changeType {
|
||||
case Renamed:
|
||||
if llen != 4 {
|
||||
return nil, fmt.Errorf("Mismatching number of fields: expect 4, got: %d", llen)
|
||||
}
|
||||
case Modified:
|
||||
if llen != 4 && llen != 3 {
|
||||
return nil, fmt.Errorf("Mismatching number of fields: expect 3..4, got: %d", llen)
|
||||
}
|
||||
default:
|
||||
if llen != 3 {
|
||||
return nil, fmt.Errorf("Mismatching number of fields: expect 3, got: %d", llen)
|
||||
}
|
||||
}
|
||||
|
||||
inodeType := inodeTypeMap[line[1]]
|
||||
if inodeType == 0 {
|
||||
return nil, fmt.Errorf("Unknown inode type '%s'", line[1])
|
||||
}
|
||||
|
||||
path, err := unescapeFilepath(line[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse filename: %v", err)
|
||||
}
|
||||
|
||||
var newPath string
|
||||
var referenceCount int
|
||||
switch changeType {
|
||||
case Renamed:
|
||||
newPath, err = unescapeFilepath(line[3])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse filename: %v", err)
|
||||
}
|
||||
case Modified:
|
||||
if llen == 4 {
|
||||
referenceCount, err = parseReferenceCount(line[3])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse reference count: %v", err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
newPath = ""
|
||||
}
|
||||
|
||||
return &InodeChange{
|
||||
Change: changeType,
|
||||
Type: inodeType,
|
||||
Path: path,
|
||||
NewPath: newPath,
|
||||
ReferenceCountChange: referenceCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// example input
|
||||
//M / /testpool/bar/
|
||||
//+ F /testpool/bar/hello.txt
|
||||
//M / /testpool/bar/hello.txt (+1)
|
||||
//M / /testpool/bar/hello-hardlink
|
||||
func parseInodeChanges(lines [][]string) ([]*InodeChange, error) {
|
||||
changes := make([]*InodeChange, len(lines))
|
||||
|
||||
for i, line := range lines {
|
||||
c, err := parseInodeChange(line)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse line %d of zfs diff: %v, got: '%s'", i, err, line)
|
||||
}
|
||||
changes[i] = c
|
||||
}
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
func listByType(t, filter string) ([]*Dataset, error) {
|
||||
args := []string{"list", "-rHp", "-t", t, "-o", dsPropListOptions}
|
||||
|
||||
if filter != "" {
|
||||
args = append(args, filter)
|
||||
}
|
||||
out, err := zfs(args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var datasets []*Dataset
|
||||
|
||||
name := ""
|
||||
var ds *Dataset
|
||||
for _, line := range out {
|
||||
if name != line[0] {
|
||||
name = line[0]
|
||||
ds = &Dataset{Name: name}
|
||||
datasets = append(datasets, ds)
|
||||
}
|
||||
if err := ds.parseLine(line); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return datasets, nil
|
||||
}
|
||||
|
||||
func propsSlice(properties map[string]string) []string {
|
||||
args := make([]string, 0, len(properties)*3)
|
||||
for k, v := range properties {
|
||||
args = append(args, "-o")
|
||||
args = append(args, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func (z *Zpool) parseLine(line []string) error {
|
||||
prop := line[1]
|
||||
val := line[2]
|
||||
|
||||
var err error
|
||||
|
||||
switch prop {
|
||||
case "name":
|
||||
setString(&z.Name, val)
|
||||
case "health":
|
||||
setString(&z.Health, val)
|
||||
case "allocated":
|
||||
err = setUint(&z.Allocated, val)
|
||||
case "size":
|
||||
err = setUint(&z.Size, val)
|
||||
case "free":
|
||||
err = setUint(&z.Free, val)
|
||||
case "fragmentation":
|
||||
// Trim trailing "%" before parsing uint
|
||||
i := strings.Index(val, "%")
|
||||
if i < 0 {
|
||||
i = len(val)
|
||||
}
|
||||
err = setUint(&z.Fragmentation, val[:i])
|
||||
case "readonly":
|
||||
z.ReadOnly = val == "on"
|
||||
case "freeing":
|
||||
err = setUint(&z.Freeing, val)
|
||||
case "leaked":
|
||||
err = setUint(&z.Leaked, val)
|
||||
case "dedupratio":
|
||||
// Trim trailing "x" before parsing float64
|
||||
z.DedupRatio, err = strconv.ParseFloat(val[:len(val)-1], 64)
|
||||
}
|
||||
return err
|
||||
}
|
Reference in New Issue
Block a user