Filesystem: Perform syscalls directly instead of executing userland

tools. Added sanity checks. Improved unit tests.
This commit is contained in:
Andrea Luzzardi 2013-01-22 12:12:16 -08:00
parent 005db1982d
commit e035f3e92b
2 changed files with 82 additions and 8 deletions

View file

@ -1,9 +1,10 @@
package docker
import (
"errors"
"fmt"
"os"
"os/exec"
"syscall"
)
type Filesystem struct {
@ -23,6 +24,9 @@ func (fs *Filesystem) createMountPoints() error {
}
func (fs *Filesystem) Mount() error {
if fs.IsMounted() {
return errors.New("Mount: Filesystem already mounted")
}
if err := fs.createMountPoints(); err != nil {
return err
}
@ -32,15 +36,33 @@ func (fs *Filesystem) Mount() error {
roBranches += fmt.Sprintf("%v=ro:", layer)
}
branches := fmt.Sprintf("br:%v:%v", rwBranch, roBranches)
cmd := exec.Command("mount", "-t", "aufs", "-o", branches, "none", fs.RootFS)
if err := cmd.Run(); err != nil {
return err
}
return nil
return syscall.Mount("none", fs.RootFS, "aufs", 0, branches)
}
func (fs *Filesystem) Umount() error {
return exec.Command("umount", fs.RootFS).Run()
if !fs.IsMounted() {
return errors.New("Umount: Filesystem not mounted")
}
return syscall.Unmount(fs.RootFS, 0)
}
func (fs *Filesystem) IsMounted() bool {
f, err := os.Open(fs.RootFS)
if err != nil {
if os.IsNotExist(err) {
return false
}
panic(err)
}
list, err := f.Readdirnames(1)
f.Close()
if err != nil {
return false
}
if len(list) > 0 {
return true
}
return false
}
func newFilesystem(rootfs string, rwpath string, layers []string) *Filesystem {

View file

@ -1,7 +1,10 @@
package docker
import (
"bytes"
"io/ioutil"
"os"
"path"
"testing"
)
@ -15,7 +18,7 @@ func TestFilesystem(t *testing.T) {
t.Fatal(err)
}
filesystem := newFilesystem(rootfs, rwpath, []string{"/var/lib/docker/images/ubuntu", "/var/lib/docker/images/test"})
filesystem := newFilesystem(rootfs, rwpath, []string{"/var/lib/docker/images/ubuntu"})
if err := filesystem.Umount(); err == nil {
t.Errorf("Umount succeeded even though the filesystem was not mounted")
@ -25,6 +28,10 @@ func TestFilesystem(t *testing.T) {
t.Fatal(err)
}
if err := filesystem.Mount(); err == nil {
t.Errorf("Double mount succeeded")
}
if err := filesystem.Umount(); err != nil {
t.Fatal(err)
}
@ -33,3 +40,48 @@ func TestFilesystem(t *testing.T) {
t.Errorf("Umount succeeded even though the filesystem was already umounted")
}
}
func TestFilesystemMultiLayer(t *testing.T) {
// Create a fake layer
fakeLayer, err := ioutil.TempDir("", "docker-layer")
if err != nil {
t.Fatal(err)
}
data := []byte("hello world")
if err := ioutil.WriteFile(path.Join(fakeLayer, "test_file"), data, 0700); err != nil {
t.Fatal(err)
}
// Create the layered filesystem and add our fake layer on top
rootfs, err := ioutil.TempDir("", "docker-test-root")
if err != nil {
t.Fatal(err)
}
rwpath, err := ioutil.TempDir("", "docker-test-rw")
if err != nil {
t.Fatal(err)
}
filesystem := newFilesystem(rootfs, rwpath, []string{"/var/lib/docker/images/ubuntu", fakeLayer})
// Mount it
if err := filesystem.Mount(); err != nil {
t.Fatal(err)
}
defer func() {
if err := filesystem.Umount(); err != nil {
t.Fatal(err)
}
}()
// Check to see whether we can access our fake layer
if _, err := os.Stat(path.Join(rootfs, "test_file")); err != nil {
t.Fatal(err)
}
fsdata, err := ioutil.ReadFile(path.Join(rootfs, "test_file"))
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(data, fsdata) {
t.Error(string(fsdata))
}
}