From cff598443114345beeae688aa4a8d5a90836e44a Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Wed, 11 Jan 2017 10:52:50 +0800 Subject: [PATCH 1/4] allow nas volume format Signed-off-by: Peng Tao --- types/validate.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/validate.go b/types/validate.go index 93d565e9..fb484e42 100644 --- a/types/validate.go +++ b/types/validate.go @@ -19,6 +19,7 @@ func (pod *UserPod) Validate() error { "vdi": true, "vfs": true, "rbd": true, + "nas": true, } hostnameLen := len(pod.Hostname) From bf3fe5f4aba35bcbd419263672187ee064dd576e Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Wed, 11 Jan 2017 10:56:22 +0800 Subject: [PATCH 2/4] add nfs volume podfile example Signed-off-by: Peng Tao --- examples/nfs-volume.pod | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 examples/nfs-volume.pod diff --git a/examples/nfs-volume.pod b/examples/nfs-volume.pod new file mode 100644 index 00000000..2c69ac57 --- /dev/null +++ b/examples/nfs-volume.pod @@ -0,0 +1,20 @@ +{ + "resource": { + "vcpu": 1, + "memory": 1024 + }, + "containers": [{ + "image": "ubuntu", + "volumes": [{ + "volume": "sharevolume", + "path": "/export", + "readOnly": false + }] + }], + "volumes": [{ + "name": "sharevolume", + "source": "192.168.80.72:/export", + "format": "nas", + "fstype": "nfs" + }] +} From 84d48ff51ebdac9cf0e9c6032443e14f6bd2a031 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 23 Jan 2017 11:25:13 +0800 Subject: [PATCH 3/4] update runv Godeps To include nfs volume support. Signed-off-by: Peng Tao --- Godeps/Godeps.json | 106 +++++++++--------- vendor/github.com/hyperhq/runv/api/helpers.go | 4 + .../hyperhq/runv/hypervisor/context.go | 20 +++- .../hyperhq/runv/hypervisor/disk.go | 12 +- .../hyperhq/runv/hypervisor/hypervisor.go | 6 + .../runv/hypervisor/qemu/qmp_handler.go | 2 + .../github.com/hyperhq/runv/hypervisor/vm.go | 86 +++++++++----- 7 files changed, 151 insertions(+), 85 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 3ba5f5cd..7f40a4f9 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "github.com/hyperhq/hyperd", "GoVersion": "go1.7", - "GodepVersion": "v76", + "GodepVersion": "v77", "Packages": [ ".", "github.com/hyperhq/hyperd/cmds/protoc-gen-gogo", @@ -1254,133 +1254,133 @@ }, { "ImportPath": "github.com/hyperhq/runv/api", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/driverloader", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/factory", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/factory/base", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/factory/cache", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/factory/direct", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/factory/multi", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/factory/single", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/factory/template", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hyperstart/api/json", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hyperstart/libhyperstart", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/libvirt", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/network", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/network/ipallocator", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/network/iptables", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/network/portmapper", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/qemu", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/types", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/vbox", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/hypervisor/xen", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/lib/govbox", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/lib/telnet", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/lib/term", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/lib/utils", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/hyperhq/runv/template", - "Comment": "v0.7.0-74-ga8930a9", - "Rev": "a8930a94146f58a8caa341c903a577e30f8f719d" + "Comment": "v0.7.0-82-ge6eebdc", + "Rev": "e6eebdc6663c73381d855581ee11028712000e3c" }, { "ImportPath": "github.com/imdario/mergo", diff --git a/vendor/github.com/hyperhq/runv/api/helpers.go b/vendor/github.com/hyperhq/runv/api/helpers.go index a14f6135..6cbfe0da 100644 --- a/vendor/github.com/hyperhq/runv/api/helpers.go +++ b/vendor/github.com/hyperhq/runv/api/helpers.go @@ -11,6 +11,10 @@ func (v *VolumeDescription) IsDir() bool { return v.Format == "vfs" } +func (v *VolumeDescription) IsNas() bool { + return v.Format == "nas" +} + func SandboxInfoFromOCF(s *specs.Spec) *SandboxConfig { return &SandboxConfig{ Hostname: s.Hostname, diff --git a/vendor/github.com/hyperhq/runv/hypervisor/context.go b/vendor/github.com/hyperhq/runv/hypervisor/context.go index 6ee429bf..20747a72 100644 --- a/vendor/github.com/hyperhq/runv/hypervisor/context.go +++ b/vendor/github.com/hyperhq/runv/hypervisor/context.go @@ -132,6 +132,22 @@ func InitContext(id string, hub chan VmEvent, client chan *types.VmResponse, dc return ctx, nil } +// SendVmEvent enqueues a VmEvent onto the context. Returns an error if there is +// no handler associated with the context. VmEvent handling happens in a +// separate goroutine, so this is thread-safe and asynchronous. +func (ctx *VmContext) SendVmEvent(ev VmEvent) error { + ctx.lock.Lock() + defer ctx.lock.Unlock() + + if ctx.handler == nil { + return fmt.Errorf("VmContext(%s): event handler already shutdown.", ctx.Id) + } + + ctx.Hub <- ev + + return nil +} + func (ctx *VmContext) setTimeout(seconds int) { if ctx.timer != nil { ctx.unsetTimeout() @@ -362,8 +378,8 @@ func (ctx *VmContext) AddVolume(vol *api.VolumeDescription, result chan api.Resu dc := NewDiskContext(ctx, vol) - if vol.IsDir() { - ctx.Log(INFO, "return volume add success for dir %s", vol.Name) + if vol.IsDir() || vol.IsNas() { + ctx.Log(INFO, "return volume add success for dir/nas %s", vol.Name) result <- api.NewResultBase(vol.Name, true, "") } else { ctx.Log(DEBUG, "insert disk for volume %s", vol.Name) diff --git a/vendor/github.com/hyperhq/runv/hypervisor/disk.go b/vendor/github.com/hyperhq/runv/hypervisor/disk.go index aeaa52e0..759ae83a 100644 --- a/vendor/github.com/hyperhq/runv/hypervisor/disk.go +++ b/vendor/github.com/hyperhq/runv/hypervisor/disk.go @@ -3,9 +3,10 @@ package hypervisor import ( "sync" - "github.com/hyperhq/runv/api" "strconv" "strings" + + "github.com/hyperhq/runv/api" ) type DiskDescriptor struct { @@ -24,6 +25,10 @@ func (d *DiskDescriptor) IsDir() bool { return d.Format == "vfs" } +func (d *DiskDescriptor) IsNas() bool { + return d.Format == "nas" +} + type DiskContext struct { *DiskDescriptor @@ -49,6 +54,9 @@ func NewDiskContext(ctx *VmContext, vol *api.VolumeDescription) *DiskContext { } if vol.IsDir() { dc.ready = true + } else if vol.IsNas() { + dc.DeviceName = vol.Source + dc.ready = true } else if vol.Format == "rbd" { dc.Options = map[string]string{ "user": vol.Options.User, @@ -107,7 +115,7 @@ func (dc *DiskContext) remove(result chan<- api.Result) { result = make(chan api.Result, 4) } - if dc.IsDir() { + if dc.IsDir() || dc.IsNas() { result <- api.NewResultBase(dc.Name, true, "no need to unplug") return } diff --git a/vendor/github.com/hyperhq/runv/hypervisor/hypervisor.go b/vendor/github.com/hyperhq/runv/hypervisor/hypervisor.go index c9c453b4..eecf8f49 100644 --- a/vendor/github.com/hyperhq/runv/hypervisor/hypervisor.go +++ b/vendor/github.com/hyperhq/runv/hypervisor/hypervisor.go @@ -23,6 +23,12 @@ func (ctx *VmContext) loop() { glog.V(1).Infof("vm %s: main event loop got message %d(%s)", ctx.Id, ev.Event(), EventString(ev.Event())) ctx.handler(ctx, ev) } + + // Unless the ctx.Hub channel is drained, processes sending operations can + // be left hanging waiting for a response. Since the handler is already + // gone, we return a fail to all these requests. + + glog.V(1).Infof("vm %s: main event loop exiting", ctx.Id) } func (ctx *VmContext) handlePAEs() { diff --git a/vendor/github.com/hyperhq/runv/hypervisor/qemu/qmp_handler.go b/vendor/github.com/hyperhq/runv/hypervisor/qemu/qmp_handler.go index cb209dc3..7c208f8f 100644 --- a/vendor/github.com/hyperhq/runv/hypervisor/qemu/qmp_handler.go +++ b/vendor/github.com/hyperhq/runv/hypervisor/qemu/qmp_handler.go @@ -150,6 +150,8 @@ func qmpReceiver(qmp chan QmpInteraction, wait chan int, decoder *json.Decoder) if msg.MessageType() == QMP_EVENT && msg.(*QmpEvent).Type == QMP_EVENT_SHUTDOWN { glog.V(0).Info("Shutdown, quit QMP receiver") + /* After shutdown, send wait notification to close qmp channel */ + close(wait) return } } diff --git a/vendor/github.com/hyperhq/runv/hypervisor/vm.go b/vendor/github.com/hyperhq/runv/hypervisor/vm.go index 12e0db6b..399476cd 100644 --- a/vendor/github.com/hyperhq/runv/hypervisor/vm.go +++ b/vendor/github.com/hyperhq/runv/hypervisor/vm.go @@ -29,7 +29,6 @@ type Vm struct { Mem int Lazy bool - Hub chan VmEvent clients *Fanout } @@ -67,7 +66,6 @@ func (vm *Vm) Launch(b *BootConfig) (err error) { ctx.Launch() vm.ctx = ctx - vm.Hub = vmEvent vm.clients = CreateFanout(Status, 128, false) return nil @@ -90,7 +88,6 @@ func (vm *Vm) AssociateVm(data []byte) error { // go vm.handlePodEvent(mypod) // - vm.Hub = PodEvent vm.clients = CreateFanout(Status, 128, false) // mypod.Status = types.S_POD_RUNNING @@ -106,20 +103,20 @@ func (vm *Vm) AssociateVm(data []byte) error { type matchResponse func(response *types.VmResponse) (error, bool) func (vm *Vm) WaitResponse(match matchResponse, timeout int) chan error { - result := make(chan error) - go func() { - var timeoutChan <-chan time.Time - if timeout >= 0 { - timeoutChan = time.After(time.Duration(timeout) * time.Second) - } else { - timeoutChan = make(chan time.Time, 1) - } + result := make(chan error, 1) + var timeoutChan <-chan time.Time + if timeout >= 0 { + timeoutChan = time.After(time.Duration(timeout) * time.Second) + } else { + timeoutChan = make(chan time.Time, 1) + } - Status, err := vm.GetResponseChan() - if err != nil { - result <- err - return - } + Status, err := vm.GetResponseChan() + if err != nil { + result <- err + return result + } + go func() { defer vm.ReleaseResponseChan(Status) for { @@ -155,7 +152,15 @@ func (vm *Vm) ReleaseVm() error { }, -1) releasePodEvent := &ReleaseVMCommand{} - vm.Hub <- releasePodEvent + + if vm.ctx == nil { + return fmt.Errorf("ReleaseVm(%s) failed: VmContext is nil", vm.Id) + } + + if err := vm.ctx.SendVmEvent(releasePodEvent); err != nil { + return err + } + return <-result } @@ -311,7 +316,14 @@ func (vm *Vm) Shutdown() api.Result { return nil, false }, -1) - vm.Hub <- &ShutdownCommand{} + if vm.ctx == nil { + return api.NewResultBase(vm.Id, false, "internal error - context == nil") + } + + if err := vm.ctx.SendVmEvent(&ShutdownCommand{}); err != nil { + return api.NewResultBase(vm.Id, false, "vm context already exited") + } + if err := <-result; err != nil { return api.NewResultBase(vm.Id, false, err.Error()) } @@ -320,10 +332,7 @@ func (vm *Vm) Shutdown() api.Result { // TODO: should we provide a method to force kill vm func (vm *Vm) Kill() { - vm.GenericOperation("KillSandbox", func(ctx *VmContext, result chan<- error) { - ctx.poweroffVM(false, "API Kill Sandbox") - result <- nil - }, StateRunning, StateTerminating) + vm.ctx.poweroffVM(false, "vm.Kill()") } func (vm *Vm) WriteFile(container, target string, data []byte) error { @@ -332,7 +341,6 @@ func (vm *Vm) WriteFile(container, target string, data []byte) error { func (vm *Vm) ReadFile(container, target string) ([]byte, error) { return vm.ctx.hyperstart.ReadFile(container, target) - } func (vm *Vm) SignalProcess(container, process string, signal syscall.Signal) error { @@ -350,7 +358,7 @@ func (vm *Vm) AddRoute() error { func (vm *Vm) AddNic(info *api.InterfaceDescription) error { client := make(chan api.Result, 1) - vm.SendGenericOperation("CreateInterface", func(ctx *VmContext, result chan<- error) { + vm.sendGenericOperation("CreateInterface", func(ctx *VmContext, result chan<- error) { go ctx.AddInterface(info, client) }, StateRunning) @@ -371,7 +379,7 @@ func (vm *Vm) AddNic(info *api.InterfaceDescription) error { func (vm *Vm) DeleteNic(id string) error { client := make(chan api.Result, 1) - vm.SendGenericOperation("NetDevRemovedEvent", func(ctx *VmContext, result chan<- error) { + vm.sendGenericOperation("NetDevRemovedEvent", func(ctx *VmContext, result chan<- error) { ctx.RemoveInterface(id, client) }, StateRunning) @@ -703,20 +711,37 @@ func (vm *Vm) GetIPAddrs() []string { return ips } -func (vm *Vm) SendGenericOperation(name string, op func(ctx *VmContext, result chan<- error), states ...string) <-chan error { +// sendGenericOperation queues a generic operation onto the VM's context if it +// is in position to handle it. +func (vm *Vm) sendGenericOperation(name string, op func(ctx *VmContext, result chan<- error), states ...string) <-chan error { result := make(chan error, 1) + + // Check vm context is available + if vm.ctx == nil { + result <- fmt.Errorf("sendGenericOperation(%s) failed: VmContext is nil", name) + return result + } + + // Setup the generic operation goe := &GenericOperation{ OpName: name, State: states, OpFunc: op, Result: result, } - vm.Hub <- goe + + // Try and send it - if we fail here, discard the channel and immediately + // push the failure state instead (goe isn't sent, so the result channel + // isn't used). + if err := vm.ctx.SendVmEvent(goe); err != nil { + result <- err + } + return result } func (vm *Vm) GenericOperation(name string, op func(ctx *VmContext, result chan<- error), states ...string) error { - return <-vm.SendGenericOperation(name, op, states...) + return <-vm.sendGenericOperation(name, op, states...) } func errorResponse(cause string) *types.VmResponse { @@ -754,18 +779,23 @@ func GetVm(vmId string, b *BootConfig, waitStarted, lazy bool) (*Vm, error) { } if waitStarted { + glog.V(1).Info("waiting for vm to start") if err := <-vm.WaitResponse(func(response *types.VmResponse) (error, bool) { if response.Code == types.E_FAILED { + glog.Error("VM start failed") return fmt.Errorf("vm start failed"), true } if response.Code == types.E_VM_RUNNING { + glog.V(1).Info("VM started successfully") return nil, true } + glog.Error("VM never started") return nil, false }, -1); err != nil { vm.Kill() } } + glog.V(1).Info("GetVm succeeded (not waiting for startup)") return vm, nil } From ab25b7426bf98b68e25f7cf4ba09b8659dcd56d0 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 7 Feb 2017 17:35:30 +0800 Subject: [PATCH 4/4] add nfs volume ci support aufs depends on 9pfs that does not have kernel export ops and thus cannot be exported by nfs-ganesha. A new testing nfs server image was introduced to work around it. Signed-off-by: Peng Tao --- hack/lib/test.sh | 17 +++++++++++++++++ hack/pods/nfs-client.pod | 21 +++++++++++++++++++++ hack/test-cmd.sh | 1 + 3 files changed, 39 insertions(+) create mode 100644 hack/pods/nfs-client.pod diff --git a/hack/lib/test.sh b/hack/lib/test.sh index 0283b4d3..95c94f4f 100644 --- a/hack/lib/test.sh +++ b/hack/lib/test.sh @@ -119,6 +119,23 @@ hyper::test::service() { hyper::test::run_attached_pod ${HYPER_ROOT}/hack/pods/service.pod } +hyper::test::nfs_volume() { + echo "create nfs volume server" + server=$(sudo hyperctl run -d hyperhq/nfs-server-tester | sed -ne "s/POD id is \(.*\)/\1/p") + ip=$(sudo hyperctl exec $server ip addr |sed -ne "s|.* \(.*\)/24.*|\1|p") + sleep 10 # nfs-server-tester takes a bit long to init in hykins + echo "create nfs volume client" + sed -e "s/NFSSERVER/$ip/" ${HYPER_ROOT}/hack/pods/nfs-client.pod > ${HYPER_TEMP}/nfs-client.pod + client=$(sudo hyperctl run -p ${HYPER_TEMP}/nfs-client.pod | sed -ne "s/POD id is \(.*\)/\1/p") + echo "check nfs file in nfs volume: /export/foo" + sleep 1 # sleep a bit to let client cmd to run + res=$(sudo hyperctl exec $server ls /export | grep foo > /dev/null 2>&1; echo $?) + echo "clean up nfs client/server" + sudo hyperctl rm $server $client + echo "check result should be 0, got: $res" + test $res -eq 0 +} + hyper::test::command() { id=$(sudo hyperctl run -t -d gcr.io/google_containers/etcd:2.0.9 /usr/local/bin/etcd | sed -ne "s/POD id is \(.*\)/\1/p") sudo hyperctl rm $id diff --git a/hack/pods/nfs-client.pod b/hack/pods/nfs-client.pod new file mode 100644 index 00000000..b8b85576 --- /dev/null +++ b/hack/pods/nfs-client.pod @@ -0,0 +1,21 @@ +{ + "resource": { + "vcpu": 1, + "memory": 256 + }, + "containers": [{ + "image": "busybox", + "command": ["/bin/sh", "-c", "touch /export/foo"], + "volumes": [{ + "volume": "sharevolume", + "path": "/export", + "readOnly": false + }] + }], + "volumes": [{ + "name": "sharevolume", + "source": "NFSSERVER:/export", + "format": "nas", + "fstype": "nfs" + }] +} diff --git a/hack/test-cmd.sh b/hack/test-cmd.sh index 7038d737..dade06ed 100755 --- a/hack/test-cmd.sh +++ b/hack/test-cmd.sh @@ -176,6 +176,7 @@ __EOF__ hyper::test::map_file hyper::test::with_volume hyper::test::service + hyper::test::nfs_volume stop_hyperd }