2017-04-26 17:39:16 +02:00
|
|
|
package zfs
|
|
|
|
|
2018-02-18 13:28:46 +01:00
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
)
|
2017-04-26 17:39:16 +02:00
|
|
|
|
2017-08-05 21:15:37 +02:00
|
|
|
type DatasetFilter interface {
|
2017-08-06 13:04:29 +02:00
|
|
|
Filter(p *DatasetPath) (pass bool, err error)
|
2017-04-26 17:39:16 +02:00
|
|
|
}
|
|
|
|
|
2019-03-19 17:43:28 +01:00
|
|
|
// Returns a DatasetFilter that does not filter (passes all paths)
|
|
|
|
func NoFilter() DatasetFilter {
|
|
|
|
return noFilter{}
|
|
|
|
}
|
2019-03-22 19:41:12 +01:00
|
|
|
|
|
|
|
type noFilter struct{}
|
2019-03-19 17:43:28 +01:00
|
|
|
|
|
|
|
var _ DatasetFilter = noFilter{}
|
|
|
|
|
|
|
|
func (noFilter) Filter(p *DatasetPath) (pass bool, err error) { return true, nil }
|
|
|
|
|
2018-12-11 22:01:50 +01:00
|
|
|
func ZFSListMapping(ctx context.Context, filter DatasetFilter) (datasets []*DatasetPath, err error) {
|
|
|
|
res, err := ZFSListMappingProperties(ctx, filter, nil)
|
2018-06-20 20:20:37 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
datasets = make([]*DatasetPath, len(res))
|
|
|
|
for i, r := range res {
|
|
|
|
datasets[i] = r.Path
|
|
|
|
}
|
|
|
|
return datasets, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type ZFSListMappingPropertiesResult struct {
|
|
|
|
Path *DatasetPath
|
|
|
|
// Guaranteed to have the same length as properties in the originating call
|
|
|
|
Fields []string
|
|
|
|
}
|
|
|
|
|
|
|
|
// properties must not contain 'name'
|
2018-12-11 22:01:50 +01:00
|
|
|
func ZFSListMappingProperties(ctx context.Context, filter DatasetFilter, properties []string) (datasets []ZFSListMappingPropertiesResult, err error) {
|
2017-05-01 20:35:04 +02:00
|
|
|
|
2017-08-05 21:15:37 +02:00
|
|
|
if filter == nil {
|
|
|
|
panic("filter must not be nil")
|
2017-05-01 20:35:04 +02:00
|
|
|
}
|
|
|
|
|
2018-06-20 20:20:37 +02:00
|
|
|
for _, p := range properties {
|
|
|
|
if p == "name" {
|
|
|
|
panic("properties must not contain 'name'")
|
|
|
|
}
|
|
|
|
}
|
2018-08-25 21:30:25 +02:00
|
|
|
newProps := make([]string, len(properties)+1)
|
2018-06-20 20:20:37 +02:00
|
|
|
newProps[0] = "name"
|
|
|
|
copy(newProps[1:], properties)
|
|
|
|
properties = newProps
|
|
|
|
|
2018-12-11 22:01:50 +01:00
|
|
|
ctx, cancel := context.WithCancel(ctx)
|
2018-02-18 13:28:46 +01:00
|
|
|
defer cancel()
|
|
|
|
rchan := make(chan ZFSListResult)
|
2017-05-01 20:35:04 +02:00
|
|
|
|
2018-06-20 20:20:37 +02:00
|
|
|
go ZFSListChan(ctx, rchan, properties, "-r", "-t", "filesystem,volume")
|
|
|
|
|
|
|
|
datasets = make([]ZFSListMappingPropertiesResult, 0)
|
2018-02-18 13:28:46 +01:00
|
|
|
for r := range rchan {
|
2017-05-01 20:35:04 +02:00
|
|
|
|
2018-06-20 20:20:37 +02:00
|
|
|
if r.Err != nil {
|
|
|
|
err = r.Err
|
2018-02-18 13:28:46 +01:00
|
|
|
return
|
|
|
|
}
|
2017-05-01 20:35:04 +02:00
|
|
|
|
2017-08-06 13:04:29 +02:00
|
|
|
var path *DatasetPath
|
2018-06-20 20:20:37 +02:00
|
|
|
if path, err = NewDatasetPath(r.Fields[0]); err != nil {
|
2017-05-01 20:35:04 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-08-05 21:15:37 +02:00
|
|
|
pass, filterErr := filter.Filter(path)
|
|
|
|
if filterErr != nil {
|
|
|
|
return nil, fmt.Errorf("error calling filter: %s", filterErr)
|
2017-05-01 20:35:04 +02:00
|
|
|
}
|
2017-08-05 21:15:37 +02:00
|
|
|
if pass {
|
2018-06-20 20:20:37 +02:00
|
|
|
datasets = append(datasets, ZFSListMappingPropertiesResult{
|
2018-08-25 21:30:25 +02:00
|
|
|
Path: path,
|
2018-06-20 20:20:37 +02:00
|
|
|
Fields: r.Fields[1:],
|
|
|
|
})
|
2017-05-01 20:35:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|