package cmd import ( "fmt" "errors" "reflect" "strconv" "strings" ) func ListDatastores(args []string, display bool) error { /*************************************************************** / Filter datastores by names given on command line /**************************************************************/ for _, d := range args { cmd := fmt.Sprintf("zfs list -p -H -o name,used,available,referenced %s", d) out, err := executeCommand(cmd) if err != nil { if strings.HasSuffix(err.Error(), "No such file or directory") { return errors.New(fmt.Sprintf("Datastore does not exist: %s", d)) } else { return errors.New(fmt.Sprintf("Error executing command %s: %v; command returned: %s\n", cmd, err, out)) } } fields := strings.Fields(out) if len(fields) < 4 { return errors.New(fmt.Sprintf("Error parsing output of \"%s\": Not enough fields", cmd)) } u, _ := strconv.ParseUint(fields[1], 10, 64) a, _ := strconv.ParseUint(fields[2], 10, 64) r, _ := strconv.ParseUint(fields[3], 10, 64) ds := Datastore{Name: d[1:], Mountpoint: d, ZFSDataset: fields[0], Used: u, Referenced: r, Available: a} err = loadDefaultsForDatastore(&ds) if err != nil { return err } gDatastores = append(gDatastores, ds) } fields := strings.Split(gDisplayDColumns, ",") if true == display { /*************************************************************** / Sort datastores / We support 3 sort criteria max /**************************************************************/ if len(gSortDSFields) > 0 && gSortDSFields != "none" { ds := initDatastoreSortStruct() // The way we manage criteria quantity is not very elegant... var fct1, fct2, fct3 *reflect.Value for i, c := range strings.Split(gSortDSFields, ",") { var fctName string if strings.HasPrefix(c, "-") { fctName = fmt.Sprintf("%sDec", strings.Replace(c, "-", "", 1)) } else { // Par defaut (pas de prefix +/-) on considere un tri incremental fctName = fmt.Sprintf("%sInc", strings.Replace(c, "+", "", 1)) } // Get function by its name fct, _, err := getStructFieldValue(ds, fctName) if err != nil { fieldName := strings.Replace(strings.Replace(c, "-", "", 1), "+", "", 1) return errors.New(fmt.Sprintf("ERROR getting DatastoreSort struct field %s. Please check the field name: %s\n", fctName, fieldName)) } switch i + 1 { case 1: fct1 = fct case 2: fct2 = fct case 3: fct3 = fct } } switch len(strings.Split(gSortDSFields, ",")) { case 1: DatastoresOrderedBy(fct1.Interface().(datastoreLessFunc)).Sort(gDatastores) case 2: DatastoresOrderedBy(fct1.Interface().(datastoreLessFunc), fct2.Interface().(datastoreLessFunc)).Sort(gDatastores) case 3: DatastoresOrderedBy(fct1.Interface().(datastoreLessFunc), fct2.Interface().(datastoreLessFunc), fct3.Interface().(datastoreLessFunc)).Sort(gDatastores) } } displayDatastoresFields(gDatastores, fields) } return nil } /******************************************************************************** * Load jails default config from $datastore/defaults.json *******************************************************************************/ func loadDefaultsForDatastore(ds *Datastore) error { jc, err := getJailConfig(fmt.Sprintf("%s/defaults.json", ds.Mountpoint)) if err != nil { return err } ds.DefaultJailConfig = jc //gDefaultConfig = append(gDefaultConfig, jc) return nil }