github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/fingerprint/storage_unix.go (about)

     1  // +build darwin dragonfly freebsd linux netbsd openbsd solaris
     2  
     3  package fingerprint
     4  
     5  import (
     6  	"fmt"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"runtime"
    10  	"strconv"
    11  	"strings"
    12  )
    13  
    14  // diskFree inspects the filesystem for path and returns the volume name and
    15  // the total and free bytes available on the file system.
    16  func (f *StorageFingerprint) diskFree(path string) (volume string, total, free uint64, err error) {
    17  	absPath, err := filepath.Abs(path)
    18  	if err != nil {
    19  		return "", 0, 0, fmt.Errorf("failed to determine absolute path for %s", path)
    20  	}
    21  
    22  	// Use -k to standardize the output values between darwin and linux
    23  	var dfArgs string
    24  	if runtime.GOOS == "linux" {
    25  		// df on linux needs the -P option to prevent linebreaks on long filesystem paths
    26  		dfArgs = "-kP"
    27  	} else {
    28  		dfArgs = "-k"
    29  	}
    30  
    31  	mountOutput, err := exec.Command("df", dfArgs, absPath).Output()
    32  	if err != nil {
    33  		return "", 0, 0, fmt.Errorf("failed to determine mount point for %s", absPath)
    34  	}
    35  	// Output looks something like:
    36  	//	Filesystem 1024-blocks      Used Available Capacity   iused    ifree %iused  Mounted on
    37  	//	/dev/disk1   487385240 423722532  63406708    87% 105994631 15851677   87%   /
    38  	//	[0] volume [1] capacity [2] SKIP  [3] free
    39  	lines := strings.Split(string(mountOutput), "\n")
    40  	if len(lines) < 2 {
    41  		return "", 0, 0, fmt.Errorf("failed to parse `df` output; expected at least 2 lines")
    42  	}
    43  	fields := strings.Fields(lines[1])
    44  	if len(fields) < 4 {
    45  		return "", 0, 0, fmt.Errorf("failed to parse `df` output; expected at least 4 columns")
    46  	}
    47  	volume = fields[0]
    48  
    49  	total, err = strconv.ParseUint(fields[1], 10, 64)
    50  	if err != nil {
    51  		return "", 0, 0, fmt.Errorf("failed to parse storage.bytestotal size in kilobytes")
    52  	}
    53  	// convert to bytes
    54  	total *= 1024
    55  
    56  	free, err = strconv.ParseUint(fields[3], 10, 64)
    57  	if err != nil {
    58  		return "", 0, 0, fmt.Errorf("failed to parse storage.bytesfree size in kilobytes")
    59  	}
    60  	// convert to bytes
    61  	free *= 1024
    62  
    63  	return volume, total, free, nil
    64  }