Example #1
0
// Create ZFS pool per specs, features and properties of pool and root dataset
func PoolCreate(name string, vdevs []VDevSpec, features map[string]string,
	props PoolProperties, fsprops ZFSProperties) (pool Pool, err error) {
	// create root vdev nvroot
	var nvroot *C.nvlist_t = nil
	if r := C.nvlist_alloc(&nvroot, C.NV_UNIQUE_NAME, 0); r != 0 {
		err = errors.New("Failed to allocate root vdev")
		return
	}
	if r := C.nvlist_add_string(nvroot, C.CString(C.ZPOOL_CONFIG_TYPE),
		C.CString(string(VDevTypeRoot))); r != 0 {
		err = errors.New("Failed to allocate root vdev")
		return
	}
	defer C.nvlist_free(nvroot)

	// Now we need to build specs (vdev hierarchy)
	if err = buildVDevSpec(nvroot, VDevTypeRoot, vdevs, props); err != nil {
		return
	}

	// convert properties
	cprops := toCPoolProperties(props)
	if cprops != nil {
		defer C.nvlist_free(cprops)
	} else if len(props) > 0 {
		err = errors.New("Failed to allocate pool properties")
		return
	}
	cfsprops := toCZFSProperties(fsprops)
	if cfsprops != nil {
		defer C.nvlist_free(cfsprops)
	} else if len(fsprops) > 0 {
		err = errors.New("Failed to allocate FS properties")
		return
	}
	for fname, fval := range features {
		sfname := fmt.Sprintf("feature@%s", fname)
		r := C.add_prop_list(C.CString(sfname), C.CString(fval), &cprops,
			C.boolean_t(1))
		if r != 0 {
			if cprops != nil {
				C.nvlist_free(cprops)
				cprops = nil
			}
			return
		}
	}

	// Create actual pool then open
	if r := C.zpool_create(libzfs_handle, C.CString(name), nvroot,
		cprops, cfsprops); r != 0 {
		err = LastError()
		return
	}
	pool, err = PoolOpen(name)
	return
}
Example #2
0
// Create dataset snapshot. Set recur to true to snapshot child datasets.
func DatasetSnapshot(path string, recur bool, props map[ZFSProp]Property) (rd Dataset, err error) {
	var cprops *C.nvlist_t
	if cprops, err = datasetPropertiesTo_nvlist(props); err != nil {
		return
	}
	defer C.nvlist_free(cprops)
	if errc := C.zfs_snapshot(libzfs_handle, C.CString(path), boolean_t(recur), cprops); errc != 0 {
		err = LastError()
		return
	}
	rd, err = DatasetOpen(path)
	return
}
Example #3
0
// Create a new filesystem or volume on path representing pool/dataset or pool/parent/dataset
func DatasetCreate(path string, dtype DatasetType,
	props map[ZFSProp]Property) (d Dataset, err error) {
	var cprops *C.nvlist_t
	if cprops, err = datasetPropertiesTo_nvlist(props); err != nil {
		return
	}
	defer C.nvlist_free(cprops)

	errcode := C.zfs_create(libzfs_handle, C.CString(path),
		C.zfs_type_t(dtype), cprops)
	if errcode != 0 {
		err = LastError()
	}
	return
}
Example #4
0
func toCZFSProperties(props ZFSProperties) (cprops *C.nvlist_t) {
	cprops = nil
	for prop, value := range props {
		name := C.zfs_prop_to_name(C.zfs_prop_t(prop))
		r := C.add_prop_list(name, C.CString(value), &cprops, C.boolean_t(0))
		if r != 0 {
			if cprops != nil {
				C.nvlist_free(cprops)
				cprops = nil
			}
			return
		}
	}
	return
}
Example #5
0
// Given a list of directories to search, find and import pool with matching
// name stored on disk.
func PoolImport(name string, searchpaths []string) (pool Pool, err error) {
	errPoolList := errors.New("Failed to list pools")
	var elem *C.nvpair_t
	var config *C.nvlist_t
	numofp := len(searchpaths)
	cpaths := C.alloc_strings(C.int(numofp))
	for i, path := range searchpaths {
		C.strings_setat(cpaths, C.int(i), C.CString(path))
	}

	pools := C.zpool_find_import(libzfs_handle, C.int(numofp), cpaths)
	defer C.nvlist_free(pools)

	elem = C.nvlist_next_nvpair(pools, elem)
	for ; elem != nil; elem = C.nvlist_next_nvpair(pools, elem) {
		var cname *C.char
		var tconfig *C.nvlist_t
		retcode := C.nvpair_value_nvlist(elem, &tconfig)
		if retcode != 0 {
			err = errPoolList
			return
		}
		retcode = C.nvlist_lookup_string(tconfig,
			C.CString(C.ZPOOL_CONFIG_POOL_NAME), &cname)
		if retcode != 0 {
			err = errPoolList
			return
		}
		oname := C.GoString(cname)
		if name == oname {
			config = tconfig
			break
		}
	}
	if config == nil {
		err = errors.New("No pools to import found with name " + name)
		return
	}

	retcode := C.zpool_import(libzfs_handle, config, C.CString(name), nil)
	if retcode != 0 {
		err = LastError()
		return
	}
	pool, err = PoolOpen(name)
	return
}
Example #6
0
// Clones the dataset.  The target must be of the same type as
// the source.
func (d *Dataset) Clone(target string, props map[ZFSProp]Property) (rd Dataset, err error) {
	var cprops *C.nvlist_t
	if d.list == nil {
		err = errors.New(msgDatasetIsNil)
		return
	}
	if cprops, err = datasetPropertiesTo_nvlist(props); err != nil {
		return
	}
	defer C.nvlist_free(cprops)
	if errc := C.zfs_clone(d.list.zh, C.CString(target), cprops); errc != 0 {
		err = LastError()
		return
	}
	rd, err = DatasetOpen(target)
	return
}