Skip to content
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

Fix 9pfs hostPath mounts and add 9pfs tests #862

Merged
merged 6 commits into from
Feb 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/flexvolume_driver/flexvolume_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ import (
"time"

"github.com/Mirantis/virtlet/pkg/flexvolume"
"github.com/Mirantis/virtlet/pkg/fs"
"github.com/Mirantis/virtlet/pkg/utils"
)

func main() {
rand.Seed(time.Now().UnixNano())
driver := flexvolume.NewDriver(utils.NewUUID, utils.NewMounter())
driver := flexvolume.NewDriver(utils.NewUUID, fs.RealFileSystem)
os.Stdout.WriteString(driver.Run(os.Args[1:]))
}
4 changes: 2 additions & 2 deletions cmd/virtlet/virtlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
"github.com/Mirantis/virtlet/pkg/cni"
"github.com/Mirantis/virtlet/pkg/config"
"github.com/Mirantis/virtlet/pkg/diag"
"github.com/Mirantis/virtlet/pkg/libvirttools"
"github.com/Mirantis/virtlet/pkg/fs"
"github.com/Mirantis/virtlet/pkg/manager"
"github.com/Mirantis/virtlet/pkg/nsfix"
"github.com/Mirantis/virtlet/pkg/tapmanager"
Expand Down Expand Up @@ -85,7 +85,7 @@ func runTapManager(config *v1.VirtletConfig) {
glog.Errorf("FD server returned error: %v", err)
os.Exit(1)
}
if err := libvirttools.ChownForEmulator(*config.FDServerSocketPath, false); err != nil {
if err := fs.RealFileSystem.ChownForEmulator(*config.FDServerSocketPath, false); err != nil {
glog.Warningf("Couldn't set tapmanager socket permissions: %v", err)
}
for {
Expand Down
13 changes: 7 additions & 6 deletions pkg/flexvolume/flexvolume.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strconv"
"strings"

"github.com/Mirantis/virtlet/pkg/fs"
"github.com/Mirantis/virtlet/pkg/utils"
)

Expand Down Expand Up @@ -53,12 +54,12 @@ type UUIDGen func() string
// https://kubernetes.io/docs/concepts/storage/volumes/#flexVolume
type Driver struct {
uuidGen UUIDGen
mounter utils.Mounter
fs fs.FileSystem
}

// NewDriver creates a Driver struct
func NewDriver(uuidGen UUIDGen, mounter utils.Mounter) *Driver {
return &Driver{uuidGen: uuidGen, mounter: mounter}
func NewDriver(uuidGen UUIDGen, fs fs.FileSystem) *Driver {
return &Driver{uuidGen: uuidGen, fs: fs}
}

func (d *Driver) populateVolumeDir(targetDir string, opts map[string]interface{}) error {
Expand Down Expand Up @@ -119,15 +120,15 @@ func (d *Driver) mount(targetMountDir, jsonOptions string) (map[string]interface
return nil, err
}

if err := d.mounter.Mount("tmpfs", targetMountDir, "tmpfs", false); err != nil {
if err := d.fs.Mount("tmpfs", targetMountDir, "tmpfs", false); err != nil {
return nil, fmt.Errorf("error mounting tmpfs at %q: %v", targetMountDir, err)
}

done := false
defer func() {
// try to unmount upon error or panic
if !done {
d.mounter.Unmount(targetMountDir, true)
d.fs.Unmount(targetMountDir, true)
}
}()

Expand All @@ -141,7 +142,7 @@ func (d *Driver) mount(targetMountDir, jsonOptions string) (map[string]interface

// Invocation: <driver executable> unmount <mount dir>
func (d *Driver) unmount(targetMountDir string) (map[string]interface{}, error) {
if err := d.mounter.Unmount(targetMountDir, true); err != nil {
if err := d.fs.Unmount(targetMountDir, true); err != nil {
return nil, fmt.Errorf("unmount %q: %v", targetMountDir, err.Error())
}

Expand Down
111 changes: 27 additions & 84 deletions pkg/flexvolume/flexvolume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ package flexvolume

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
"strings"
"testing"

fakefs "github.com/Mirantis/virtlet/pkg/fs/fake"
"github.com/Mirantis/virtlet/pkg/utils"
testutils "github.com/Mirantis/virtlet/pkg/utils/testing"
)
Expand All @@ -35,75 +34,6 @@ const (
fakeUUID = "abb67e3c-71b3-4ddd-5505-8c4215d5c4eb"
)

type fakeMounter struct {
t *testing.T
tmpDir string
journal []string
}

var _ utils.Mounter = &fakeMounter{}

func newFakeMounter(t *testing.T, tmpDir string) *fakeMounter {
return &fakeMounter{t: t, tmpDir: tmpDir}
}

func (mounter *fakeMounter) validatePath(target string) {
if filepath.Dir(target) != filepath.Clean(mounter.tmpDir) {
mounter.t.Fatalf("bad path encountered by the mounter: %q (tmpDir %q)", target, mounter.tmpDir)
}
}

func (mounter *fakeMounter) Mount(source string, target string, fstype string, bind bool) error {
mounter.validatePath(target)
mounter.journal = append(mounter.journal, fmt.Sprintf("mount: %s %s %s %v", source, target, fstype, bind))

// We want to check directory contents both before & after mount,
// see comment in FlexVolumeDriver.mount() in flexvolume.go.
// So we move the original contents to .shadowed subdir.
shadowedPath := filepath.Join(target, ".shadowed")
if err := os.Mkdir(shadowedPath, 0755); err != nil {
mounter.t.Fatalf("os.Mkdir(): %v", err)
}

pathsToShadow, err := filepath.Glob(filepath.Join(target, "*"))
if err != nil {
mounter.t.Fatalf("filepath.Glob(): %v", err)
}
for _, pathToShadow := range pathsToShadow {
filename := filepath.Base(pathToShadow)
if filename == ".shadowed" {
continue
}
if err := os.Rename(pathToShadow, filepath.Join(shadowedPath, filename)); err != nil {
mounter.t.Fatalf("os.Rename(): %v", err)
}
}
return nil
}

func (mounter *fakeMounter) Unmount(target string, detach bool) error {
// we make sure that path is under our tmpdir before wiping it
mounter.validatePath(target)
mounter.journal = append(mounter.journal, fmt.Sprintf("unmount: %s %v", target, detach))

paths, err := filepath.Glob(filepath.Join(target, "*"))
if err != nil {
mounter.t.Fatalf("filepath.Glob(): %v", err)
}
for _, path := range paths {
if filepath.Base(path) != ".shadowed" {
continue
}
if err := os.RemoveAll(path); err != nil {
mounter.t.Fatalf("os.RemoveAll(): %v", err)
}
}

// We don't clean up '.shadowed' dir here because flexvolume driver
// recursively removes the whole dir tree anyway.
return nil
}

func TestFlexVolume(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "flexvolume-test")
if err != nil {
Expand Down Expand Up @@ -134,7 +64,7 @@ func TestFlexVolume(t *testing.T) {
message string
fields map[string]interface{}
files map[string]interface{}
mountJournal []string
mountJournal []*testutils.Record
}{
{
name: "init",
Expand Down Expand Up @@ -185,17 +115,23 @@ func TestFlexVolume(t *testing.T) {
"virtlet-flexvolume.json": utils.ToJSONUnindented(cephJSONVolumeInfo),
},
},
mountJournal: []string{
fmt.Sprintf("mount: tmpfs %s tmpfs false", cephDir),
mountJournal: []*testutils.Record{
{
Name: "Mount",
Value: []interface{}{"tmpfs", cephDir, "tmpfs", false},
},
},
},
{
name: "unmount-ceph",
args: []string{"unmount", cephDir},
status: "Success",
subdir: "ceph",
mountJournal: []string{
fmt.Sprintf("unmount: %s true", cephDir),
mountJournal: []*testutils.Record{
{
Name: "Unmount",
Value: []interface{}{cephDir, true},
},
},
},
{
Expand All @@ -209,17 +145,23 @@ func TestFlexVolume(t *testing.T) {
"virtlet-flexvolume.json": utils.ToJSONUnindented(cephJSONVolumeInfo),
},
},
mountJournal: []string{
fmt.Sprintf("mount: tmpfs %s tmpfs false", cephDir),
mountJournal: []*testutils.Record{
{
Name: "Mount",
Value: []interface{}{"tmpfs", cephDir, "tmpfs", false},
},
},
},
{
name: "unmount-ceph-1",
args: []string{"unmount", cephDir},
status: "Success",
subdir: "ceph",
mountJournal: []string{
fmt.Sprintf("unmount: %s true", cephDir),
mountJournal: []*testutils.Record{
{
Name: "Unmount",
Value: []interface{}{cephDir, true},
},
},
},
{
Expand Down Expand Up @@ -256,10 +198,11 @@ func TestFlexVolume(t *testing.T) {
t.Run(step.name, func(t *testing.T) {
var subdir string
args := step.args
mounter := newFakeMounter(t, tmpDir)
rec := testutils.NewToplevelRecorder()
fs := fakefs.NewFakeFileSystem(t, rec, tmpDir, nil)
d := NewDriver(func() string {
return fakeUUID
}, mounter)
}, fs)
result := d.Run(args)
var m map[string]interface{}
if err := json.Unmarshal([]byte(result), &m); err != nil {
Expand Down Expand Up @@ -299,8 +242,8 @@ func TestFlexVolume(t *testing.T) {
t.Errorf("bad file content.\n%s\n-- instead of --\n%s", utils.ToJSON(files), utils.ToJSON(step.files))
}
}
if !reflect.DeepEqual(mounter.journal, step.mountJournal) {
t.Errorf("unexpected mount journal: %#v instead of %#v", mounter.journal, step.mountJournal)
if !reflect.DeepEqual(rec.Content(), step.mountJournal) {
t.Errorf("unexpected mount journal: %#v instead of %#v", rec.Content(), step.mountJournal)
}
})
}
Expand Down
Loading