1
0
Fork 0

Correct qemu arguments

timestamps
dump_stack() 2018-09-19 06:13:28 +00:00
parent e923c7c3c8
commit a41de84157
2 changed files with 83 additions and 11 deletions

View File

@ -8,6 +8,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"math/rand"
"net"
"os" "os"
"os/exec" "os/exec"
"syscall" "syscall"
@ -58,8 +60,12 @@ type Kernel struct {
// QemuSystem describe qemu parameters and runned process // QemuSystem describe qemu parameters and runned process
type QemuSystem struct { type QemuSystem struct {
arch arch arch arch
kernel Kernel kernel Kernel
drivePath string
Cpus int
Memory int
// accessible while qemu is runned // accessible while qemu is runned
cmd *exec.Cmd cmd *exec.Cmd
@ -76,7 +82,7 @@ type QemuSystem struct {
} }
// NewQemuSystem constructor // NewQemuSystem constructor
func NewQemuSystem(arch arch, kernel Kernel) (q QemuSystem, err error) { func NewQemuSystem(arch arch, kernel Kernel, drivePath string) (q QemuSystem, err error) {
if _, err = exec.LookPath("qemu-system-" + string(arch)); err != nil { if _, err = exec.LookPath("qemu-system-" + string(arch)); err != nil {
return return
} }
@ -87,15 +93,63 @@ func NewQemuSystem(arch arch, kernel Kernel) (q QemuSystem, err error) {
} }
q.kernel = kernel q.kernel = kernel
if _, err = os.Stat(drivePath); err != nil {
return
}
q.drivePath = drivePath
// Default values
q.Cpus = 2
q.Memory = 512 // megabytes
return return
} }
func getRandomAddrPort() (addr string) {
// 127.1-255.0-255.0-255:10000-50000
ip := fmt.Sprintf("127.%d.%d.%d",
rand.Int()%254+1, rand.Int()%255, rand.Int()%254)
port := rand.Int()%40000 + 10000
return fmt.Sprintf("%s:%d", ip, port)
}
func getFreeAddrPort() (addrPort string) {
for {
addrPort = getRandomAddrPort()
ln, err := net.Listen("tcp", addrPort)
if err == nil {
ln.Close()
return
}
}
}
func kvmExists() bool {
if _, err := os.Stat("/dev/kvm"); err != nil {
return false
}
return true
}
// Start qemu process // Start qemu process
func (q *QemuSystem) Start() (err error) { func (q *QemuSystem) Start() (err error) {
q.cmd = exec.Command("qemu-system-"+string(q.arch), rand.Seed(time.Now().UnixNano()) // Are you sure?
// TODO hostfwd := fmt.Sprintf("hostfwd=tcp:%s-:22", getFreeAddrPort())
"-snapshot", qemuArgs := []string{"-snapshot", "-nographic",
"-nographic") "-hda", q.drivePath,
"-kernel", q.kernel.Path,
"-append", "root=/dev/sda console=ttyS0 rw",
"-smp", fmt.Sprintf("%d", q.Cpus),
"-m", fmt.Sprintf("%d", q.Memory),
"-device", "e1000,netdev=n1",
"-netdev", "user,id=n1," + hostfwd,
}
if (q.arch == X86_64 || q.arch == I386) && kvmExists() {
qemuArgs = append(qemuArgs, "-enable-kvm")
}
q.cmd = exec.Command("qemu-system-"+string(q.arch), qemuArgs...)
if q.pipe.stdin, err = q.cmd.StdinPipe(); err != nil { if q.pipe.stdin, err = q.cmd.StdinPipe(); err != nil {
return return

View File

@ -5,12 +5,13 @@
package qemukernel package qemukernel
import ( import (
"net"
"testing" "testing"
) )
func TestQemuSystemNew_InvalidKernelPath(t *testing.T) { func TestQemuSystemNew_InvalidKernelPath(t *testing.T) {
kernel := Kernel{Name: "Invalid", Path: "/invalid/path"} kernel := Kernel{Name: "Invalid", Path: "/invalid/path"}
if _, err := NewQemuSystem(X86_64, kernel); err == nil { if _, err := NewQemuSystem(X86_64, kernel, "/bin/sh"); err == nil {
t.Fatal(err) t.Fatal(err)
} }
} }
@ -18,7 +19,15 @@ func TestQemuSystemNew_InvalidKernelPath(t *testing.T) {
func TestQemuSystemNew_InvalidQemuArch(t *testing.T) { func TestQemuSystemNew_InvalidQemuArch(t *testing.T) {
// FIXME put kernel image to path not just "any valid path" // FIXME put kernel image to path not just "any valid path"
kernel := Kernel{Name: "Valid path", Path: "/bin/sh"} kernel := Kernel{Name: "Valid path", Path: "/bin/sh"}
if _, err := NewQemuSystem(unsupported, kernel); err == nil { if _, err := NewQemuSystem(unsupported, kernel, "/bin/sh"); err == nil {
t.Fatal(err)
}
}
func TestQemuSystemNew_InvalidQemuDrivePath(t *testing.T) {
// FIXME put kernel image to path not just "any valid path"
kernel := Kernel{Name: "Valid path", Path: "/bin/sh"}
if _, err := NewQemuSystem(X86_64, kernel, "/invalid/path"); err == nil {
t.Fatal(err) t.Fatal(err)
} }
} }
@ -26,7 +35,7 @@ func TestQemuSystemNew_InvalidQemuArch(t *testing.T) {
func TestQemuSystemNew(t *testing.T) { func TestQemuSystemNew(t *testing.T) {
// FIXME put kernel image to path not just "any valid path" // FIXME put kernel image to path not just "any valid path"
kernel := Kernel{Name: "Valid path", Path: "/bin/sh"} kernel := Kernel{Name: "Valid path", Path: "/bin/sh"}
if _, err := NewQemuSystem(X86_64, kernel); err != nil { if _, err := NewQemuSystem(X86_64, kernel, "/bin/sh"); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
@ -34,7 +43,7 @@ func TestQemuSystemNew(t *testing.T) {
func TestQemuSystemStart(t *testing.T) { func TestQemuSystemStart(t *testing.T) {
// TODO check kernel path on other distros than gentoo // TODO check kernel path on other distros than gentoo
kernel := Kernel{Name: "Host kernel", Path: "/boot/vmlinuz-4.18.8"} kernel := Kernel{Name: "Host kernel", Path: "/boot/vmlinuz-4.18.8"}
qemu, err := NewQemuSystem(X86_64, kernel) qemu, err := NewQemuSystem(X86_64, kernel, "/bin/sh")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -45,3 +54,12 @@ func TestQemuSystemStart(t *testing.T) {
qemu.Stop() qemu.Stop()
} }
func TestGetFreeAddrPort(t *testing.T) {
addrPort := getFreeAddrPort()
ln, err := net.Listen("tcp", addrPort)
if err != nil {
t.Fatal(err)
}
ln.Close()
}