work on stable version
This commit is contained in:
parent
70b35932cb
commit
a0f6f3a6a0
59
main.go
59
main.go
@ -12,8 +12,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/melbahja/goph"
|
||||
@ -34,8 +32,7 @@ type Credentials struct {
|
||||
|
||||
type Controller struct {
|
||||
cancel context.CancelFunc
|
||||
Stdout *bytes.Buffer
|
||||
Stderr *bytes.Buffer
|
||||
cmd *exec.Cmd
|
||||
}
|
||||
|
||||
func (c *Controller) Stop() {
|
||||
@ -63,41 +60,35 @@ func StartMachine(machine types.Machine) *Controller {
|
||||
ctrl := &Controller{}
|
||||
|
||||
go func() {
|
||||
command := machine.Expand()
|
||||
ctx, cfunc := context.WithCancel(context.TODO())
|
||||
ctrl.cancel = cfunc
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
var cmd *exec.Cmd
|
||||
if runtime.GOOS == "windows" {
|
||||
cmd = exec.Command("powershell.exe", command)
|
||||
} else {
|
||||
cmd = exec.Command("bash", "-c", command)
|
||||
}
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
ctrl.Stderr = &stderr
|
||||
ctrl.Stdout = &stdout
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
cmd := exec.Command(fmt.Sprintf("qemu-system-%v", machine.Arch), machine.Expand()...)
|
||||
fmt.Println(cmd.String())
|
||||
cmd.Stdout = &stderr
|
||||
cmd.Stderr = &stdout
|
||||
ctrl.cmd = cmd
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
fmt.Println("running...", cmd.Process.Pid)
|
||||
|
||||
//syscall.Kill(cmd.Process.Pid, syscall.SIGTERM)
|
||||
go func() {
|
||||
err := cmd.Wait()
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
cfunc()
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
fmt.Println("Killing Process")
|
||||
//err := KillProcess(string(machine.Arch))
|
||||
//err := cmd.Process.Signal(syscall.SIGTERM)
|
||||
err := cmd.Process.Kill()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -144,28 +135,16 @@ func main() {
|
||||
NoGraphic: types.Set,
|
||||
HardDiskA: `./imgs/UbuntuTest.img`,
|
||||
}
|
||||
// ctrl := StartMachine(machine)
|
||||
command := machine.Expand()
|
||||
fmt.Println(command)
|
||||
// this works, we need to format like this
|
||||
cmd := exec.Command("qemu-system-x86_64", "-m", "size=4096", "-smp", "cpus=4", "-accel", "accel=whpx", "-boot", "order=c,menu=off", "-nic", "tap,ifname=qemu-tap", "-nographic", "-hda", "./imgs/UbuntuTest.img")
|
||||
cmd.Start()
|
||||
ctrl := StartMachine(machine)
|
||||
|
||||
fmt.Println("Press enter to stop machine")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
_, _ = reader.ReadString('\n')
|
||||
cmd.Process.Kill()
|
||||
// ctrl.Stop()
|
||||
|
||||
ctrl.Stop()
|
||||
fmt.Println("Press enter to exit")
|
||||
_, _ = reader.ReadString('\n')
|
||||
|
||||
// if errout != "" {
|
||||
// panic(fmt.Errorf("%v", errout))
|
||||
// }
|
||||
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// }
|
||||
|
||||
// Start new ssh connection with private key.
|
||||
|
||||
//client, err := goph.New("baseimguser", "127.0.0.1", goph.Password("food99"))
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
package machine
|
||||
|
||||
// qemu-system-x86_64.exe -m 4096 -accel whpx -boot d -smp 4 -net nic -net user,hostfwd=tcp::8888-:22 -hda .\imgs\ubuntu_server_test.img -nographic
|
||||
@ -1,4 +1,11 @@
|
||||
package types
|
||||
package accel
|
||||
|
||||
type (
|
||||
VMExit string
|
||||
Accelerator string
|
||||
Thread string
|
||||
KernelIrqchip string
|
||||
)
|
||||
|
||||
const (
|
||||
KVM Accelerator = "kvm"
|
||||
@ -22,7 +29,7 @@ const (
|
||||
)
|
||||
|
||||
type Accel struct {
|
||||
Accelerator Accelerator `json:"accel,omitempty"`
|
||||
Accelerator Accelerator `json:"accel,omitempty" omit:"tag"`
|
||||
// enable Xen integrated Intel graphics passthrough, default=off
|
||||
IGDPassthrough *bool `json:"igd-passthru,omitempty"`
|
||||
// controls accelerated irqchip support (default=on
|
||||
@ -1,4 +1,4 @@
|
||||
package types
|
||||
package boot
|
||||
|
||||
// floppy (a), hard disk (c), CD-ROM (d), network (n)
|
||||
type Drives string
|
||||
@ -20,7 +20,7 @@ const (
|
||||
|
||||
type Boot struct {
|
||||
// Order of boot
|
||||
Order []Drives `json:"order,omitempty"`
|
||||
Order []Drives `json:"order,omitempty" omit:"tag"`
|
||||
Once []Drives `json:"once,omitempty"`
|
||||
Menu *bool `json:"menu,omitempty"`
|
||||
// The file's name that would be passed to bios as logo picture, if menu=on
|
||||
@ -6,6 +6,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/rayaman/go-qemu/pkg/types/accel"
|
||||
"github.com/rayaman/go-qemu/pkg/types/boot"
|
||||
"github.com/rayaman/go-qemu/pkg/types/numa"
|
||||
)
|
||||
|
||||
@ -30,14 +32,14 @@ type Machine struct {
|
||||
// Amount of memory in MB
|
||||
Memory Memory `json:"m,omitempty"`
|
||||
// Number of CPU cores
|
||||
Cores SMP `json:"smp,omitempty"`
|
||||
Cpu CHIP `json:"cpu,omitempty"`
|
||||
Accel Accel `json:"accel,omitempty"`
|
||||
Boot Boot `json:"boot,omitempty"`
|
||||
Numa numa.Numa `json:"numa,omitempty" omit:"true"`
|
||||
MemoryPath string `json:"memory-path,omitempty"`
|
||||
MemoryPrealloc Flag `json:"memory-prealloc,omitempty"`
|
||||
Nic NIC `json:"nic,omitempty"`
|
||||
Cores SMP `json:"smp,omitempty"`
|
||||
Cpu CHIP `json:"cpu,omitempty"`
|
||||
Accel accel.Accel `json:"accel,omitempty"`
|
||||
Boot boot.Boot `json:"boot,omitempty"`
|
||||
Numa numa.Numa `json:"numa,omitempty" omit:"true"`
|
||||
MemoryPath string `json:"memory-path,omitempty"`
|
||||
MemoryPrealloc Flag `json:"memory-prealloc,omitempty"`
|
||||
Nic NIC `json:"nic,omitempty"`
|
||||
|
||||
// Graphics
|
||||
NoGraphic Flag `json:"nographic,omitempty"`
|
||||
@ -52,7 +54,16 @@ type Machine struct {
|
||||
CDROM string `json:"cdrom,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Machine) Expand() string {
|
||||
func remove(s []string, r string) []string {
|
||||
for i, v := range s {
|
||||
if v == r {
|
||||
return append(s[:i], s[i+1:]...)
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (m *Machine) Expand() []string {
|
||||
fields := structs.Fields(m)
|
||||
exp := []string{}
|
||||
for _, field := range fields {
|
||||
@ -61,29 +72,30 @@ func (m *Machine) Expand() string {
|
||||
if tag != "" {
|
||||
if field.Kind() == reflect.Struct || field.Kind() == reflect.Interface && !field.IsZero() {
|
||||
if omit != "" {
|
||||
exp = append(exp, Expand(field.Value()))
|
||||
exp = append(exp, Expand(field.Value())...)
|
||||
} else {
|
||||
exp = append(exp, Expand(field.Value(), tag))
|
||||
exp = append(exp, Expand(field.Value(), tag)...)
|
||||
}
|
||||
} else {
|
||||
if !field.IsZero() {
|
||||
if strings.Contains(fmt.Sprintf("%v", field.Value()), " ") {
|
||||
exp = append(exp, fmt.Sprintf(`-%v "%v"`, tag, field.Value()))
|
||||
if fmt.Sprintf("%v", field.Value()) == "flag-on" {
|
||||
exp = append(exp, "-"+tag)
|
||||
} else {
|
||||
exp = append(exp, fmt.Sprintf("-%v %v", tag, field.Value()))
|
||||
exp = append(exp, "-"+tag, fmt.Sprintf("%v", field.Value()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.ReplaceAll(strings.ReplaceAll(fmt.Sprintf("qemu-system-%v %v", m.Arch, strings.Join(exp, " ")), " flag-on", ""), " ", " ")
|
||||
exp = remove(exp, "")
|
||||
return exp
|
||||
}
|
||||
|
||||
func Expand(obj any, tag ...string) string {
|
||||
func Expand(obj any, tag ...string) []string {
|
||||
opts := []string{}
|
||||
fields := structs.Fields(obj)
|
||||
useSpace := false
|
||||
|
||||
for _, field := range fields {
|
||||
opt := strings.ReplaceAll(field.Tag("json"), ",omitempty", "")
|
||||
opt = strings.ReplaceAll(opt, "omitempty", "")
|
||||
@ -103,58 +115,50 @@ func Expand(obj any, tag ...string) string {
|
||||
opts = append(opts, fmt.Sprintf("%v=%v-%v", opt, value.First, value.Last))
|
||||
}
|
||||
case []numa.Node:
|
||||
useSpace = true
|
||||
for _, node := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(node))
|
||||
opts = append(opts, "-numa", opt)
|
||||
opts = append(opts, Expand(node)...)
|
||||
}
|
||||
case []numa.Dist:
|
||||
useSpace = true
|
||||
for _, dist := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(dist))
|
||||
opts = append(opts, "-numa", opt)
|
||||
opts = append(opts, Expand(dist)...)
|
||||
}
|
||||
case []numa.CPU:
|
||||
useSpace = true
|
||||
for _, cpu := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(cpu))
|
||||
opts = append(opts, "-numa", opt)
|
||||
opts = append(opts, Expand(cpu)...)
|
||||
}
|
||||
case []numa.HMATLB:
|
||||
useSpace = true
|
||||
for _, hmatlb := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(hmatlb))
|
||||
opts = append(opts, "-numa", opt)
|
||||
opts = append(opts, Expand(hmatlb)...)
|
||||
}
|
||||
case []numa.HMATCache:
|
||||
useSpace = true
|
||||
for _, hmatcache := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(hmatcache))
|
||||
opts = append(opts, "-numa", opt)
|
||||
opts = append(opts, Expand(hmatcache)...)
|
||||
}
|
||||
case Options:
|
||||
opts = append(opts, value.ExpandOptions())
|
||||
case []Drives:
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, strings.Join(ConvertDrives(value), ",")))
|
||||
opts = append(opts, value.ExpandOptions()...)
|
||||
case []boot.Drives:
|
||||
if omit == "tag" {
|
||||
opts = append(opts, fmt.Sprintf("%v", strings.Join(boot.ConvertDrives(value), ",")))
|
||||
} else {
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, strings.Join(boot.ConvertDrives(value), ",")))
|
||||
}
|
||||
default:
|
||||
if omit == "" {
|
||||
if strings.Contains(fmt.Sprintf("%v", value), " ") {
|
||||
opts = append(opts, fmt.Sprintf(`%v="%v"`, opt, value))
|
||||
} else {
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, value))
|
||||
}
|
||||
} else {
|
||||
if strings.Contains(fmt.Sprintf("%v", value), " ") {
|
||||
opts = append(opts, fmt.Sprintf(`"%v"`, value))
|
||||
} else {
|
||||
opts = append(opts, fmt.Sprintf("%v", value))
|
||||
}
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, value))
|
||||
} else if omit == "tag" {
|
||||
opts = append(opts, fmt.Sprintf("%v", value))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
otag := ""
|
||||
if len(tag) > 0 {
|
||||
otag = "-" + tag[0] + " "
|
||||
return []string{"-" + tag[0], strings.Join(opts, ",")}
|
||||
} else {
|
||||
return []string{strings.Join(opts, ",")}
|
||||
}
|
||||
if useSpace {
|
||||
return otag + strings.Join(opts, " ")
|
||||
}
|
||||
return otag + strings.Join(opts, ",")
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
package types
|
||||
|
||||
import "strings"
|
||||
|
||||
type (
|
||||
NICType string
|
||||
)
|
||||
|
||||
// TODO: Implement other types user,socket,brtidge
|
||||
|
||||
const (
|
||||
TAP NICType = "tap"
|
||||
Bridge NICType = "bridge"
|
||||
@ -16,22 +20,22 @@ type TapOptions struct {
|
||||
IFName string `json:"ifname,omitempty"`
|
||||
}
|
||||
|
||||
func (t *TapOptions) ExpandOptions() string {
|
||||
return Expand(t)
|
||||
func (t *TapOptions) ExpandOptions() []string {
|
||||
return []string{"tap," + strings.Join(Expand(t), ",")}
|
||||
}
|
||||
|
||||
type BridgeOptions struct {
|
||||
}
|
||||
|
||||
func (b *BridgeOptions) ExpandOptions() string {
|
||||
return ""
|
||||
func (b *BridgeOptions) ExpandOptions() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
type UserOptions struct {
|
||||
}
|
||||
|
||||
func (u *UserOptions) ExpandOptions() string {
|
||||
return ""
|
||||
func (u *UserOptions) ExpandOptions() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
type SocketOptions struct {
|
||||
@ -44,12 +48,12 @@ type SocketOptions struct {
|
||||
Connect string `json:"connect,omitempty"`
|
||||
}
|
||||
|
||||
func (s *SocketOptions) ExpandOptions() string {
|
||||
return Expand(s)
|
||||
func (s *SocketOptions) ExpandOptions() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
type Options interface {
|
||||
ExpandOptions() string
|
||||
ExpandOptions() []string
|
||||
}
|
||||
|
||||
type NIC struct {
|
||||
|
||||
@ -16,7 +16,7 @@ Note: Different machines may have different subsets of the CPU topology
|
||||
*/
|
||||
type SMP struct {
|
||||
// The number of initial CPUs
|
||||
Cpus uint `json:"cpus,omitempty"`
|
||||
Cpus uint `json:"cpus,omitempty" omit:"tag"`
|
||||
// Maximum number of total CPUs, including offline CPUs for hotplug, etc
|
||||
MaxCpus uint `json:"maxcpus,omitempty"`
|
||||
// Number of drawers on the machine board
|
||||
|
||||
@ -8,10 +8,6 @@ type (
|
||||
CompressionType string
|
||||
Format string
|
||||
System string
|
||||
Accelerator string
|
||||
VMExit string
|
||||
Thread string
|
||||
KernelIrqchip string
|
||||
Flag string
|
||||
)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user