Filesystem: Perform syscalls directly instead of executing userland
tools. Added sanity checks. Improved unit tests.
This commit is contained in:
parent
005db1982d
commit
e035f3e92b
2 changed files with 82 additions and 8 deletions
|
@ -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 {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue