Skip to content

Commit

Permalink
Issue mistifyio#39 and Issue mistifyio#40 -
Browse files Browse the repository at this point in the history
Enable Solaris support for go-zfs
Switch from zfs/zpool get to zfs/zpool list for better performance
Signed-off-by: Amit Krishnan <krish.amit@gmail.com>
  • Loading branch information
amitkris committed Feb 10, 2016
1 parent 16b13ca commit cb9f9c0
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 66 deletions.
76 changes: 32 additions & 44 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package zfs

import (
"bytes"
"errors"
"fmt"
"io"
"os/exec"
"regexp"
"runtime"
"strconv"
"strings"

Expand Down Expand Up @@ -91,34 +93,25 @@ func setUint(field *uint64, value string) error {
}

func (ds *Dataset) parseLine(line []string) error {
prop := line[1]
val := line[2]

var err error

switch prop {
case "available":
err = setUint(&ds.Avail, val)
case "compression":
setString(&ds.Compression, val)
case "mountpoint":
setString(&ds.Mountpoint, val)
case "quota":
err = setUint(&ds.Quota, val)
case "type":
setString(&ds.Type, val)
case "origin":
setString(&ds.Origin, val)
case "used":
err = setUint(&ds.Used, val)
case "volsize":
err = setUint(&ds.Volsize, val)
case "written":
err = setUint(&ds.Written, val)
case "logicalused":
err = setUint(&ds.Logicalused, val)
if len(line) != len(DsPropList) {
return errors.New("ZFS output does not match what is expected" +
"on this platform")
}
return err
setString(&ds.Name, line[0])
setString(&ds.Avail, line[3])
setString(&ds.Compression, line[5])
setString(&ds.Mountpoint, line[4])
setString(&ds.Quota, line[8])
setString(&ds.Type, line[6])
setString(&ds.Origin, line[1])
setString(&ds.Used, line[2])
setString(&ds.Volsize, line[7])

if runtime.GOOS != "solaris" {
setString(&ds.Written, line[9])
setString(&ds.Logicalused, line[10])
}
return nil
}

/*
Expand Down Expand Up @@ -267,15 +260,15 @@ func parseInodeChanges(lines [][]string) ([]*InodeChange, error) {
}

func listByType(t, filter string) ([]*Dataset, error) {
args := []string{"get", "-rHp", "-t", t, "all"}
args := []string{"list", "-rH", "-t", t, "-o", strings.Join(DsPropList, ",")}

if filter != "" {
args = append(args, filter)
}
out, err := zfs(args...)
if err != nil {
return nil, err
}

var datasets []*Dataset

name := ""
Expand Down Expand Up @@ -304,20 +297,15 @@ func propsSlice(properties map[string]string) []string {
}

func (z *Zpool) parseLine(line []string) error {
prop := line[1]
val := line[2]

var err error

switch prop {
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)
if len(line) != len(ZpoolPropList) {
return errors.New("Zpool output not what is expected on" +
"this platform")
}
return err
setString(&z.Name, line[0])
setString(&z.Health, line[1])
setString(&z.Allocated, line[2])
setString(&z.Size, line[3])
setString(&z.Free, line[4])

return nil
}
9 changes: 9 additions & 0 deletions utils_notsolaris.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build !solaris

package zfs

// List of ZFS properties to retrieve from zfs list command on a non-Solaris platform
var DsPropList = []string{"name", "origin", "used", "available", "mountpoint", "compression", "type", "volsize", "quota", "written", "logicalused"}

// List of Zpool properties to retrieve from zpool list command on a non-Solaris platform
var ZpoolPropList = []string{"name", "health", "allocated", "size", "free"}
9 changes: 9 additions & 0 deletions utils_solaris.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build solaris

package zfs

// List of ZFS properties to retrieve from zfs list command on a Solaris platform
var DsPropList = []string{"name", "origin", "used", "available", "mountpoint", "compression", "type", "volsize", "quota"}

// List of Zpool properties to retrieve from zpool list command on a Solaris platform
var ZpoolPropList = []string{"name", "health", "allocated", "size", "free"}
28 changes: 14 additions & 14 deletions zfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,17 @@ const (
// The field definitions can be found in the ZFS manual:
// http://www.freebsd.org/cgi/man.cgi?zfs(8).
type Dataset struct {
Name string
Origin string
Used uint64
Avail uint64
Mountpoint string
Compression string
Type string
Written uint64
Volsize uint64
Usedbydataset uint64
Logicalused uint64
Quota uint64
Name string
Origin string
Used string
Avail string
Mountpoint string
Compression string
Type string
Written string
Volsize string
Logicalused string
Quota string
}

// InodeType is the type of inode as reported by Diff
Expand Down Expand Up @@ -145,7 +144,7 @@ func Volumes(filter string) ([]*Dataset, error) {
// GetDataset retrieves a single ZFS dataset by name. This dataset could be
// any valid ZFS dataset type, such as a clone, filesystem, snapshot, or volume.
func GetDataset(name string) (*Dataset, error) {
out, err := zfs("get", "-Hp", "all", name)
out, err := zfs("list", "-Hp", "-o", strings.Join(DsPropList, ","), name)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -403,13 +402,14 @@ func (d *Dataset) Rollback(destroyMoreRecent bool) error {
// A recursion depth may be specified, or a depth of 0 allows unlimited
// recursion.
func (d *Dataset) Children(depth uint64) ([]*Dataset, error) {
args := []string{"get", "-t", "all", "-Hp", "all"}
args := []string{"list"}
if depth > 0 {
args = append(args, "-d")
args = append(args, strconv.FormatUint(depth, 10))
} else {
args = append(args, "-r")
}
args = append(args, "-t", "all", "-Hp", "-o", strings.Join(DsPropList, ","))
args = append(args, d.Name)

out, err := zfs(args...)
Expand Down
20 changes: 16 additions & 4 deletions zfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
"path/filepath"
"reflect"
"runtime"
"strconv"
"testing"
"time"

"github.com/mistifyio/go-zfs"
zfs "github.com/mistifyio/go-zfs"
)

func sleep(delay int) {
Expand Down Expand Up @@ -78,7 +79,12 @@ func TestDatasets(t *testing.T) {
ok(t, err)
equals(t, zfs.DatasetFilesystem, ds.Type)
equals(t, "", ds.Origin)
assert(t, ds.Logicalused > 0, "Logicalused is not greater than 0")
if runtime.GOOS != "solaris" {
lused, err := strconv.ParseUint(ds.Logicalused, 10, 64)
ok(t, err)
assert(t, lused != 0, "Logicalused is not"+
"greater than 0")
}
})
}

Expand Down Expand Up @@ -264,8 +270,14 @@ func TestListZpool(t *testing.T) {
zpoolTest(t, func() {
pools, err := zfs.ListZpools()
ok(t, err)
equals(t, "test", pools[0].Name)

var i int
var pool *zfs.Zpool
for i, pool = range pools {
if pool.Name == "test" {
break
}
}
equals(t, "test", pools[i].Name)
})
}

Expand Down
12 changes: 8 additions & 4 deletions zpool.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package zfs

import (
"strings"
)

// ZFS zpool states, which can indicate if a pool is online, offline,
// degraded, etc. More information regarding zpool states can be found here:
// https://docs.oracle.com/cd/E19253-01/819-5461/gamno/index.html.
Expand All @@ -17,9 +21,9 @@ const (
type Zpool struct {
Name string
Health string
Allocated uint64
Size uint64
Free uint64
Allocated string
Size string
Free string
}

// zpool is a helper function to wrap typical calls to zpool.
Expand All @@ -30,7 +34,7 @@ func zpool(arg ...string) ([][]string, error) {

// GetZpool retrieves a single ZFS zpool by name.
func GetZpool(name string) (*Zpool, error) {
out, err := zpool("get", "all", "-p", name)
out, err := zpool("list", "-o", strings.Join(ZpoolPropList, ","), name)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit cb9f9c0

Please sign in to comment.