New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for setting storage size on ZFS containers #21946

Merged
merged 3 commits into from Jun 8, 2016
Jump to file or symbol
Failed to load files and symbols.
+93 −11
Diff settings

Always

Just for now

@@ -5,12 +5,16 @@ package graphtest
import (
"fmt"
"io/ioutil"
"math/rand"
"os"
"path"
"reflect"
"syscall"
"testing"
"unsafe"
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/go-units"
)
var (
@@ -297,3 +301,45 @@ func DriverTestCreateSnap(t *testing.T, drivername string) {
t.Fatal(err)
}
}
func writeRandomFile(path string, size uint64) error {
buf := make([]int64, size/8)
r := rand.NewSource(0)
for i := range buf {
buf[i] = r.Int63()
}
// Cast to []byte
header := *(*reflect.SliceHeader)(unsafe.Pointer(&buf))
header.Len *= 8
header.Cap *= 8
data := *(*[]byte)(unsafe.Pointer(&header))
return ioutil.WriteFile(path, data, 0700)
}
// DriverTestSetQuota Create a driver and test setting quota.
func DriverTestSetQuota(t *testing.T, drivername string) {
driver := GetDriver(t, drivername)
defer PutDriver(t)
createBase(t, driver, "Base")
storageOpt := make(map[string]string, 1)
storageOpt["size"] = "50M"
if err := driver.Create("zfsTest", "Base", "", storageOpt); err != nil {
t.Fatal(err)
}
mountPath, err := driver.Get("zfsTest", "")
if err != nil {
t.Fatal(err)
}
quota := uint64(50 * units.MiB)
err = writeRandomFile(path.Join(mountPath, "file"), quota*2)
if pathError, ok := err.(*os.PathError); ok && pathError.Err != syscall.EDQUOT {
t.Fatalf("expect write() to fail with %v, got %v", syscall.EDQUOT, err)
}
}
Copy path View file
@@ -250,11 +250,7 @@ func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[s
// Create prepares the dataset and filesystem for the ZFS driver for the given id under the parent.
func (d *Driver) Create(id string, parent string, mountLabel string, storageOpt map[string]string) error {
if len(storageOpt) != 0 {
return fmt.Errorf("--storage-opt is not supported for zfs")
}
err := d.create(id, parent)
err := d.create(id, parent, storageOpt)
if err == nil {
return nil
}
@@ -273,22 +269,58 @@ func (d *Driver) Create(id string, parent string, mountLabel string, storageOpt
}
// retry
return d.create(id, parent)
return d.create(id, parent, storageOpt)
}
func (d *Driver) create(id, parent string) error {
func (d *Driver) create(id, parent string, storageOpt map[string]string) error {
name := d.zfsPath(id)
quota, err := parseStorageOpt(storageOpt)

This comment has been minimized.

@thaJeztah

thaJeztah Apr 30, 2016

Member

Should err be checked here?

This comment has been minimized.

@thaJeztah

thaJeztah Apr 30, 2016

Member

Perhaps return early on error (also below), because there's now a lot of nested if's (but that's just a suggestion)

if err != nil {
return err
}
if parent == "" {
mountoptions := map[string]string{"mountpoint": "legacy"}
fs, err := zfs.CreateFilesystem(name, mountoptions)
if err == nil {
d.Lock()
d.filesystemsCache[fs.Name] = true
d.Unlock()
err = setQuota(name, quota)
if err == nil {
d.Lock()
d.filesystemsCache[fs.Name] = true
d.Unlock()
}
}
return err
}
return d.cloneFilesystem(name, d.zfsPath(parent))
err = d.cloneFilesystem(name, d.zfsPath(parent))
if err == nil {
err = setQuota(name, quota)
}
return err
}
func parseStorageOpt(storageOpt map[string]string) (string, error) {
// Read size to change the disk quota per container
for k, v := range storageOpt {
key := strings.ToLower(k)
switch key {
case "size":
return v, nil
default:
return "0", fmt.Errorf("Unknown option %s", key)
}
}
return "0", nil
}
func setQuota(name string, quota string) error {
if quota == "0" {
return nil
}
fs, err := zfs.GetDataset(name)
if err != nil {
return err
}
return fs.SetProperty("quota", quota)
}
// Remove deletes the dataset, filesystem and the cache for the given id.
@@ -26,6 +26,10 @@ func TestZfsCreateSnap(t *testing.T) {
graphtest.DriverTestCreateSnap(t, "zfs")
}
func TestZfsSetQuota(t *testing.T) {
graphtest.DriverTestSetQuota(t, "zfs")
}
func TestZfsTeardown(t *testing.T) {
graphtest.PutDriver(t)
}
ProTip! Use n and p to navigate between commits in a pull request.