working on commands
This commit is contained in:
parent
e3cadeff08
commit
70b35932cb
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
imgs/*
|
||||
isos/*
|
||||
keys/*
|
||||
system info.ini
|
||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Ryan Ward
|
||||
Copyright (c) 2025 Ryan Ward
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
31
baseimg setup.md
Normal file
31
baseimg setup.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Base Image Setups
|
||||
|
||||
Defaults
|
||||
---
|
||||
User: `baseimguser`
|
||||
Pass: `baseimgpass`
|
||||
|
||||
All base images should use these credentials. Once a new image is built off of these they should create new users and delete the old base user.
|
||||
|
||||
- Install [openssh-client/server](https://www.tecmint.com/install-openssh-server-in-linux/)
|
||||
- Install net-tools (apt install net-tools)
|
||||
- Install inetutils-ping (apt install inetutils-ping)
|
||||
- Install firewall (apt install ufw)
|
||||
- Install nmcli (apt install network-manager)
|
||||
- Install yq (apt install yq)
|
||||
|
||||
Configure TAP networking:
|
||||
---
|
||||
refer to [windows setup](https://wonghoi.humgar.com/blog/2021/05/03/qemu-for-windows-host-quirks/)
|
||||
|
||||
|
||||
|
||||
Base Images To support:
|
||||
---
|
||||
- Ubuntu/Debian
|
||||
- Rocky/AlmaLinux
|
||||
Strech goal
|
||||
- Windows
|
||||
- MacOS
|
||||
|
||||
`qemu-system-x86_64.exe -m 4096 -accel whpx -boot c -smp 4 -nic tap,ifname=qemu-tap -hda .\imgs\UbuntuTest.img -nographic`
|
||||
28
go.mod
Normal file
28
go.mod
Normal file
@ -0,0 +1,28 @@
|
||||
module github.com/rayaman/go-qemu
|
||||
|
||||
go 1.22.0
|
||||
|
||||
require (
|
||||
github.com/abdfnx/gosh v0.4.0
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/melbahja/goph v1.4.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.5 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/random-names/go v0.0.0-20190609025437-4cca751ffd3b // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/crypto v0.6.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
)
|
||||
83
go.sum
Normal file
83
go.sum
Normal file
@ -0,0 +1,83 @@
|
||||
github.com/abdfnx/gosh v0.4.0 h1:cBvmHw8yV3oXiAcORpi7Oip+MT6/5HBMOrvpn0cZNYM=
|
||||
github.com/abdfnx/gosh v0.4.0/go.mod h1:MUTJRMc7FpBb/bFnZ2U0hj48zj8284J1cS3AUiIRZ/o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/melbahja/goph v1.4.0 h1:z0PgDbBFe66lRYl3v5dGb9aFgPy0kotuQ37QOwSQFqs=
|
||||
github.com/melbahja/goph v1.4.0/go.mod h1:uG+VfK2Dlhk+O32zFrRlc3kYKTlV6+BtvPWd/kK7U68=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go=
|
||||
github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/random-names/go v0.0.0-20190609025437-4cca751ffd3b h1:zoygtqmtDrSdPPrII/yf2pY1J2w4f3Nw/TOZQ0M4Bbo=
|
||||
github.com/random-names/go v0.0.0-20190609025437-4cca751ffd3b/go.mod h1:SJUWdwBnVA1OEPaBWTAHgKveCUkJbFm8UnQ53wYFUTk=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
294
main.go
Normal file
294
main.go
Normal file
@ -0,0 +1,294 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/melbahja/goph"
|
||||
"github.com/rayaman/go-qemu/pkg/image"
|
||||
"github.com/rayaman/go-qemu/pkg/image/formats"
|
||||
"github.com/rayaman/go-qemu/pkg/types"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Credentials struct {
|
||||
User string `json:"user"`
|
||||
Pass string `json:"pass"`
|
||||
MachineID string `json:"machine_id"`
|
||||
PublicKeyPath string `json:"public_key_path"`
|
||||
PrivateKeyPath string `json:"private_key_path"`
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
cancel context.CancelFunc
|
||||
Stdout *bytes.Buffer
|
||||
Stderr *bytes.Buffer
|
||||
}
|
||||
|
||||
func (c *Controller) Stop() {
|
||||
c.cancel()
|
||||
}
|
||||
|
||||
func KillProcess(name string) error {
|
||||
processes, err := process.Processes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, p := range processes {
|
||||
n, err := p.Name()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == name {
|
||||
return p.Kill()
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("process not found")
|
||||
}
|
||||
|
||||
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{}
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("running...", cmd.Process.Pid)
|
||||
|
||||
//syscall.Kill(cmd.Process.Pid, syscall.SIGTERM)
|
||||
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)
|
||||
}
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return ctrl
|
||||
}
|
||||
|
||||
func main() {
|
||||
// var img image.Image = &formats.QCOW2{
|
||||
// ImageName: "imgs/UbuntuTest.img",
|
||||
// BackingFile: "base/UbuntuBase.img",
|
||||
// BackingFmt: "qcow2",
|
||||
// }
|
||||
|
||||
// var img image.Image = &formats.QCOW2{
|
||||
// ImageName: "imgs/NetworkTest.img",
|
||||
// }
|
||||
|
||||
// err := image.Create(img, types.GetSize(types.GB, 8), image.Options{IsBaseImage: true})
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
machine := types.Machine{
|
||||
Arch: types.X86_64,
|
||||
Cores: types.SMP{
|
||||
Cpus: 4,
|
||||
},
|
||||
Boot: types.Boot{
|
||||
Order: []types.Drives{types.HARDDISK},
|
||||
Menu: types.Off,
|
||||
},
|
||||
Memory: types.Memory{
|
||||
Size: 4096,
|
||||
},
|
||||
Accel: types.Accel{
|
||||
Accelerator: types.WHPX,
|
||||
},
|
||||
Nic: types.NIC{
|
||||
Type: types.TAP,
|
||||
Options: &types.TapOptions{
|
||||
IFName: "qemu-tap",
|
||||
},
|
||||
},
|
||||
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()
|
||||
fmt.Println("Press enter to stop machine")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
_, _ = reader.ReadString('\n')
|
||||
cmd.Process.Kill()
|
||||
// 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"))
|
||||
// _, err := SetUpMachine()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
|
||||
// auth, err := goph.Key("keys/3e6e04c3-1af4-41e7-8984-c60012034075", "")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// client, err := goph.NewConn(&goph.Config{
|
||||
// User: "baseimguser",
|
||||
// Addr: "127.0.0.1",
|
||||
// Port: 8888,
|
||||
// Auth: auth,
|
||||
// Timeout: goph.DefaultTimeout,
|
||||
// Callback: ssh.InsecureIgnoreHostKey(),
|
||||
// })
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
|
||||
// defer client.Close()
|
||||
|
||||
// out, err := client.Run(`echo 'baseimgpass' | sudo -S ls /tmp`)
|
||||
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
|
||||
// fmt.Println(string(out))
|
||||
// SetUpMachine(types.GetSize(types.GB, 64))
|
||||
}
|
||||
|
||||
func SetUpMachine(size types.Size) (*Credentials, error) {
|
||||
machine_id := uuid.New().String()
|
||||
private_path := filepath.Join("keys", machine_id)
|
||||
public_path := filepath.Join("keys", machine_id+".pub")
|
||||
err := MakeSSHKeyPair(public_path, private_path)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img := &formats.QCOW2{
|
||||
ImageName: fmt.Sprintf("imgs/%v.img", machine_id),
|
||||
BackingFile: "base/UbuntuBase.img",
|
||||
BackingFmt: "qcow2",
|
||||
}
|
||||
|
||||
err = image.Create(img, size)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ToDo start Machine
|
||||
|
||||
Config := &Credentials{
|
||||
MachineID: machine_id,
|
||||
PublicKeyPath: public_path,
|
||||
PrivateKeyPath: private_path,
|
||||
}
|
||||
|
||||
client, err := goph.NewConn(&goph.Config{
|
||||
User: "baseimguser",
|
||||
Addr: "127.0.0.1",
|
||||
Port: 8888,
|
||||
Auth: goph.Password("baseimgpass"),
|
||||
Timeout: goph.DefaultTimeout,
|
||||
Callback: ssh.InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer client.Close()
|
||||
|
||||
err = client.Upload(public_path, "/home/baseimguser/.ssh/authorized_keys")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmds := []string{
|
||||
// Allow us to use our private key to connect directly into root user
|
||||
`cp /home/baseimguser/.ssh/authorized_keys /root/.ssh/authorized_keys`,
|
||||
}
|
||||
|
||||
for _, cmd := range cmds {
|
||||
out, err := client.Run(`echo 'baseimgpass' | sudo -S ` + cmd)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Got Error: %v --- %v", string(out), err)
|
||||
}
|
||||
}
|
||||
|
||||
return Config, nil
|
||||
}
|
||||
|
||||
func MakeSSHKeyPair(pubKeyPath, privateKeyPath string) error {
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privateKeyFile, err := os.Create(privateKeyPath)
|
||||
defer privateKeyFile.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
|
||||
if err := pem.Encode(privateKeyFile, privateKeyPEM); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0655)
|
||||
}
|
||||
106
pkg/image/cmd_create.go
Normal file
106
pkg/image/cmd_create.go
Normal file
@ -0,0 +1,106 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/abdfnx/gosh"
|
||||
"github.com/rayaman/go-qemu/pkg/types"
|
||||
)
|
||||
|
||||
func getOptions(m map[string]string) string {
|
||||
str := []string{}
|
||||
for k, v := range m {
|
||||
if len(v) > 0 {
|
||||
str = append(str, fmt.Sprintf("%v=%v", k, v))
|
||||
}
|
||||
}
|
||||
n_str := strings.Join(str, ",")
|
||||
if len(n_str) > 0 {
|
||||
return "-o \"" + strings.Join(str, ",") + "\" "
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getData(m map[string]string, key string) (string, bool) {
|
||||
if d, ok := m[key]; ok {
|
||||
delete(m, key)
|
||||
if len(d) == 0 {
|
||||
return "", false
|
||||
}
|
||||
return d, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func getMap(q any) map[string]string {
|
||||
m := map[string]string{}
|
||||
v := reflect.ValueOf(q).Elem()
|
||||
for j := 0; j < v.NumField(); j++ { // Go through all fields of struct
|
||||
if !v.Field(j).IsZero() {
|
||||
index := strings.ReplaceAll(v.Type().Field(j).Tag.Get("json"), ",omitempty", "")
|
||||
if v.Field(j).Type() == reflect.TypeOf(true) {
|
||||
m[index] = types.SW[v.Field(j).Bool()]
|
||||
} else {
|
||||
m[index] = v.Field(j).String()
|
||||
}
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
IsBaseImage bool `json:"is_base_image"`
|
||||
}
|
||||
|
||||
// create [--object OBJECTDEF] [-q] [-f FMT] [-b BACKING_FILE [-F BACKING_FMT]] [-u] [-o OPTIONS] FILENAME [SIZE]
|
||||
|
||||
// Creates an image based of the supplied image
|
||||
func Create(i Image, size types.Size, opts ...Options) error {
|
||||
|
||||
data := getMap(i)
|
||||
|
||||
var imagename string
|
||||
var ok bool
|
||||
|
||||
if imagename, ok = getData(data, "image_name"); !(ok && imagename != "") {
|
||||
return fmt.Errorf("invalid image data, ImageName is not optional")
|
||||
}
|
||||
|
||||
os.MkdirAll(filepath.Join(filepath.Dir(imagename), "/base"), os.ModePerm)
|
||||
basepath := filepath.Dir(imagename)
|
||||
basename := filepath.Base(imagename)
|
||||
|
||||
if len(opts) > 0 && opts[0].IsBaseImage {
|
||||
imagename = filepath.Join(basepath, "base", basename)
|
||||
}
|
||||
|
||||
additional := []string{}
|
||||
if backing_file, ok := getData(data, "backing_file"); ok {
|
||||
additional = append(additional, "-b "+backing_file+" ")
|
||||
}
|
||||
|
||||
if backing_fmt, ok := getData(data, "backing_fmt"); ok {
|
||||
additional = append(additional, "-F "+backing_fmt+" ")
|
||||
}
|
||||
|
||||
format := string(strings.ReplaceAll(strings.ToLower(reflect.TypeOf(i).String()), "*formats.", ""))
|
||||
cmd := fmt.Sprintf("qemu-img create -f %s %v%v%v %v", format, strings.Join(additional, ""), getOptions(data), imagename, size)
|
||||
|
||||
// Todo remove this when done testing
|
||||
fmt.Println(cmd)
|
||||
err, _, errout := gosh.RunOutput(cmd)
|
||||
|
||||
if errout != "" {
|
||||
return fmt.Errorf("%v", errout)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
3
pkg/image/formats/luks.go
Normal file
3
pkg/image/formats/luks.go
Normal file
@ -0,0 +1,3 @@
|
||||
package formats
|
||||
|
||||
// ToDo implement this
|
||||
3
pkg/image/formats/qcow.go
Normal file
3
pkg/image/formats/qcow.go
Normal file
@ -0,0 +1,3 @@
|
||||
package formats
|
||||
|
||||
// ToDo implement this
|
||||
76
pkg/image/formats/qcow2.go
Normal file
76
pkg/image/formats/qcow2.go
Normal file
@ -0,0 +1,76 @@
|
||||
package formats
|
||||
|
||||
import (
|
||||
"github.com/rayaman/go-qemu/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
types.RegisterType("qcow2", QCOW2{})
|
||||
}
|
||||
|
||||
type QCOW2 struct {
|
||||
// Name of the image
|
||||
ImageName string `json:"image_name"`
|
||||
// Determines the qcow2 version to use. compat=0.10 uses the traditional image format that can be read by any QEMU since 0.10. compat=1.1 enables image format extensions that only QEMU 1.1 and newer understand (this is the default). Amongst others, this includes zero clusters, which allow efficient copy-on-read for sparse images
|
||||
Compat types.Compat `json:"compat,omitempty"`
|
||||
// File name of a base image
|
||||
BackingFile string `json:"backing_file,omitempty"`
|
||||
// Image format of the base image
|
||||
BackingFmt string `json:"backing_fmt,omitempty"`
|
||||
// This option configures which compression algorithm will be used for compressed clusters on the image. Note that setting this option doesn’t yet cause the image to actually receive compressed writes. It is most commonly used with the -c option of qemu-img convert, but can also be used with the compress filter driver or backup block jobs with compression enabled.
|
||||
CompressionType types.CompressionType `json:"compression_type,omitempty"`
|
||||
/*
|
||||
If this option is set to true, the image is encrypted with 128-bit AES-CBC.
|
||||
|
||||
The use of encryption in qcow and qcow2 images is considered to be flawed by modern cryptography standards, suffering from a number of design problems:
|
||||
|
||||
* The AES-CBC cipher is used with predictable initialization vectors based on the sector number. This makes it vulnerable to chosen plaintext attacks which can reveal the existence of encrypted data.
|
||||
|
||||
* The user passphrase is directly used as the encryption key. A poorly chosen or short passphrase will compromise the security of the encryption.
|
||||
|
||||
* In the event of the passphrase being compromised there is no way to change the passphrase to protect data in any qcow images. The files must be cloned, using a different encryption passphrase in the new file. The original file must then be securely erased using a program like shred, though even this is ineffective with many modern storage technologies.
|
||||
|
||||
* Initialization vectors used to encrypt sectors are based on the guest virtual sector number, instead of the host physical sector. When a disk image has multiple internal snapshots this means that data in multiple physical sectors is encrypted with the same initialization vector. With the CBC mode, this opens the possibility of watermarking attacks if the attack can collect multiple sectors encrypted with the same IV and some predictable data. Having multiple qcow2 images with the same passphrase also exposes this weakness since the passphrase is directly used as the key.
|
||||
|
||||
Use of qcow / qcow2 encryption is thus strongly discouraged. Users are recommended to use an alternative encryption technology such as the Linux dm-crypt / LUKS system.
|
||||
*/
|
||||
Encryption bool `json:"encryption,omitempty"`
|
||||
// Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster sizes can improve the image file size whereas larger cluster sizes generally provide better performance.
|
||||
ClusterSize string `json:"cluster_size,omitempty"`
|
||||
// Preallocation mode (allowed values: off, metadata, falloc, full). An image with preallocated metadata is initially larger but can improve performance when the image needs to grow. falloc and full preallocations are like the same options of raw format, but sets up metadata also.
|
||||
Preallocation types.Preallocation `json:"preallocation,omitempty"`
|
||||
/*
|
||||
If this option is set to true, reference count updates are postponed with the goal of avoiding metadata I/O and improving performance. This is particularly interesting with cache=writethrough which doesn’t batch metadata updates. The tradeoff is that after a host crash, the reference count tables must be rebuilt, i.e. on the next open an (automatic) qemu-img check -r all is required, which may take some time.
|
||||
|
||||
This option can only be enabled if compat=1.1 is specified.
|
||||
*/
|
||||
LazyRefcounts bool `json:"lazy_refcounts,omitempty"`
|
||||
/*
|
||||
If this option is set to true, it will turn off COW of the file. It’s only valid on btrfs, no effect on other file systems.
|
||||
|
||||
Btrfs has low performance when hosting a VM image file, even more when the guest on the VM also using btrfs as file system. Turning off COW is a way to mitigate this bad performance. Generally there are two ways to turn off COW on btrfs:
|
||||
|
||||
* Disable it by mounting with nodatacow, then all newly created files will be NOCOW
|
||||
|
||||
* For an empty file, add the NOCOW file attribute. That’s what this option does.
|
||||
|
||||
Note: this option is only valid to new or empty files. If there is an existing file which is COW and has data blocks already, it couldn’t be changed to NOCOW by setting nocow=on. One can issue lsattr filename to check if the NOCOW flag is set or not (Capital ‘C’ is NOCOW flag).
|
||||
*/
|
||||
NoCow bool `json:"nocow,omitempty"`
|
||||
/*
|
||||
Filename where all guest data will be stored. If this option is used, the qcow2 file will only contain the image’s metadata.
|
||||
|
||||
Note: Data loss will occur if the given filename already exists when using this option with qemu-img create since qemu-img will create the data file anew, overwriting the file’s original contents. To simply update the reference to point to the given pre-existing file, use qemu-img amend.
|
||||
*/
|
||||
DataFile string `json:"data_file,omitempty"`
|
||||
/*
|
||||
If this option is set to true, QEMU will always keep the external data file consistent as a standalone read-only raw image.
|
||||
|
||||
It does this by forwarding all write accesses to the qcow2 file through to the raw data file, including their offsets. Therefore, data that is visible on the qcow2 node (i.e., to the guest) at some offset is visible at the same offset in the raw data file. This results in a read-only raw image. Writes that bypass the qcow2 metadata may corrupt the qcow2 metadata because the out-of-band writes may result in the metadata falling out of sync with the raw image.
|
||||
|
||||
If this option is off, QEMU will use the data file to store data in an arbitrary manner. The file’s content will not make sense without the accompanying qcow2 metadata. Where data is written will have no relation to its offset as seen by the guest, and some writes (specifically zero writes) may not be forwarded to the data file at all, but will only be handled by modifying qcow2 metadata.
|
||||
|
||||
This option can only be enabled if data_file is set.
|
||||
*/
|
||||
DataFileRaw bool `json:"data_file_raw,omitempty"`
|
||||
}
|
||||
3
pkg/image/formats/qed.go
Normal file
3
pkg/image/formats/qed.go
Normal file
@ -0,0 +1,3 @@
|
||||
package formats
|
||||
|
||||
// ToDo implement this
|
||||
16
pkg/image/formats/raw.go
Normal file
16
pkg/image/formats/raw.go
Normal file
@ -0,0 +1,16 @@
|
||||
package formats
|
||||
|
||||
import (
|
||||
"github.com/rayaman/go-qemu/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
types.RegisterType("raw", Raw{})
|
||||
}
|
||||
|
||||
type Raw struct {
|
||||
// Name of the image
|
||||
ImageName string `json:"image_name"`
|
||||
// Preallocation mode (allowed values: off, falloc, full). falloc mode preallocates space for image by calling posix_fallocate(). full mode preallocates space for image by writing data to underlying storage. This data may or may not be zero, depending on the storage location.
|
||||
Preallocation types.Preallocation `json:"preallocation"`
|
||||
}
|
||||
3
pkg/image/formats/vdi.go
Normal file
3
pkg/image/formats/vdi.go
Normal file
@ -0,0 +1,3 @@
|
||||
package formats
|
||||
|
||||
// ToDo implement this
|
||||
3
pkg/image/formats/vhdx.go
Normal file
3
pkg/image/formats/vhdx.go
Normal file
@ -0,0 +1,3 @@
|
||||
package formats
|
||||
|
||||
// ToDo implement this
|
||||
3
pkg/image/formats/vmdk.go
Normal file
3
pkg/image/formats/vmdk.go
Normal file
@ -0,0 +1,3 @@
|
||||
package formats
|
||||
|
||||
// ToDo implement this
|
||||
3
pkg/image/formats/vpc.go
Normal file
3
pkg/image/formats/vpc.go
Normal file
@ -0,0 +1,3 @@
|
||||
package formats
|
||||
|
||||
// ToDo implement this
|
||||
71
pkg/image/image.go
Normal file
71
pkg/image/image.go
Normal file
@ -0,0 +1,71 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/rayaman/go-qemu/pkg/types"
|
||||
)
|
||||
|
||||
// Reperesents a qemu image
|
||||
type Image interface {
|
||||
//GetType() types.Format
|
||||
}
|
||||
|
||||
type holder struct {
|
||||
Format string
|
||||
Image any
|
||||
}
|
||||
|
||||
// Loades a saved Image into memory
|
||||
func LoadImage(path string) (Image, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var h = &holder{}
|
||||
|
||||
err = json.Unmarshal(data, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err = json.Marshal(h.Image)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t := reflect.New(reflect.TypeOf(types.GetTypes()[h.Format])).Interface()
|
||||
err = json.Unmarshal(data, t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// Saves an image to disk
|
||||
func SaveImage(path string, img Image) error {
|
||||
|
||||
data, err := json.MarshalIndent(holder{
|
||||
Format: strings.ReplaceAll(strings.ToLower(reflect.TypeOf(img).String()), "*formats.", ""),
|
||||
Image: img,
|
||||
}, "", "\t")
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := os.Create(path)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = file.Write(data)
|
||||
|
||||
return err
|
||||
}
|
||||
3
pkg/system/machine/machine.go
Normal file
3
pkg/system/machine/machine.go
Normal file
@ -0,0 +1,3 @@
|
||||
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
pkg/system/system.go
Normal file
1
pkg/system/system.go
Normal file
@ -0,0 +1 @@
|
||||
package system
|
||||
50
pkg/types/accel.go
Normal file
50
pkg/types/accel.go
Normal file
@ -0,0 +1,50 @@
|
||||
package types
|
||||
|
||||
const (
|
||||
KVM Accelerator = "kvm"
|
||||
XEN Accelerator = "xen"
|
||||
HVF Accelerator = "hvf"
|
||||
NVMM Accelerator = "nvmm"
|
||||
// Windows
|
||||
WHPX Accelerator = "whpx"
|
||||
TCG Accelerator = "tcg"
|
||||
|
||||
Run VMExit = "run"
|
||||
InternalError VMExit = "internal-error"
|
||||
Disable VMExit = "disable"
|
||||
|
||||
Single Thread = "single"
|
||||
Multi Thread = "multi"
|
||||
|
||||
KernelOn KernelIrqchip = "on"
|
||||
KernelOff KernelIrqchip = "off"
|
||||
KernelSplit KernelIrqchip = "split"
|
||||
)
|
||||
|
||||
type Accel struct {
|
||||
Accelerator Accelerator `json:"accel,omitempty"`
|
||||
// enable Xen integrated Intel graphics passthrough, default=off
|
||||
IGDPassthrough *bool `json:"igd-passthru,omitempty"`
|
||||
// controls accelerated irqchip support (default=on
|
||||
KernelIrqchip KernelIrqchip `json:"kernel-irqchip,omitempty"`
|
||||
// size of KVM shadow MMU in bytes
|
||||
KVMShadowMem uint `json:"kvm-shadow-mem,omitempty"`
|
||||
// one guest instruction per TCG translation block
|
||||
OneINSNPerTB *bool `json:"one-insn-per-tb,omitempty"`
|
||||
// enable TCG split w^x mapping
|
||||
SplitWX *bool `json:"split-wx,omitempty"`
|
||||
// TCG translation block cache size
|
||||
TBSize uint `json:"tb-size,omitempty"`
|
||||
// KVM dirty ring GFN count, default 0
|
||||
DirtyRingSize uint `json:"dirty-ring-size,omitempty"`
|
||||
// KVM Eager Page Split chunk size, default 0, disabled. ARM only
|
||||
EagerSplitSize uint `json:"eager-split-size,omitempty"`
|
||||
// enable notify VM exit and set notify window, x86 only
|
||||
NotifyVMExit VMExit `json:"notify-vm-exit,omitempty"`
|
||||
// enable notify VM exit and set notify window, x86 only
|
||||
NotifyWindow *bool `json:"notify-window,omitempty"`
|
||||
// enable multi-threaded TCG
|
||||
Thread Thread `json:"thread,omitempty"`
|
||||
// KVM device path, default /dev/kvm
|
||||
Device string `json:"device,omitempty"`
|
||||
}
|
||||
33
pkg/types/boot.go
Normal file
33
pkg/types/boot.go
Normal file
@ -0,0 +1,33 @@
|
||||
package types
|
||||
|
||||
// floppy (a), hard disk (c), CD-ROM (d), network (n)
|
||||
type Drives string
|
||||
|
||||
func ConvertDrives(d []Drives) []string {
|
||||
var res []string
|
||||
for _, v := range d {
|
||||
res = append(res, string(v))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
const (
|
||||
CDROM Drives = "d"
|
||||
FLOPPY Drives = "a"
|
||||
HARDDISK Drives = "c"
|
||||
NETWORK Drives = "n"
|
||||
)
|
||||
|
||||
type Boot struct {
|
||||
// Order of boot
|
||||
Order []Drives `json:"order,omitempty"`
|
||||
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
|
||||
SplashFile string `json:"splash,omitempty"`
|
||||
// The period that splash picture last if menu=on, unit is ms
|
||||
SplashTime uint `json:"splash-time,omitempty"`
|
||||
// The timeout before guest reboot when boot failed, unit is ms
|
||||
RebootTime uint `json:"reboot-timeout,omitempty"`
|
||||
Strict *bool `json:"strict,omitempty"`
|
||||
}
|
||||
541
pkg/types/chip.go
Normal file
541
pkg/types/chip.go
Normal file
@ -0,0 +1,541 @@
|
||||
package types
|
||||
|
||||
type CHIP string
|
||||
|
||||
type CPUID string
|
||||
|
||||
const (
|
||||
C486 CHIP = "486" // (alias configured by machine type)
|
||||
C486V1 CHIP = "486-v1" //
|
||||
Broadwell CHIP = "Broadwell" // (alias configured by machine type)
|
||||
BroadwellIBRS CHIP = "Broadwell-IBRS" // (alias of Broadwell-v3)
|
||||
BroadwellNoTSX CHIP = "Broadwell-noTSX" // (alias of Broadwell-v2)
|
||||
BroadwellNoTSXIBRS CHIP = "Broadwell-noTSX-IBRS" // (alias of Broadwell-v4)
|
||||
BroadwellV1 CHIP = "Broadwell-v1" // Intel Core Processor (Broadwell)
|
||||
BroadwellV2 CHIP = "Broadwell-v2" // Intel Core Processor (Broadwell, no TSX)
|
||||
BroadwellV3 CHIP = "Broadwell-v3" // Intel Core Processor (Broadwell, IBRS)
|
||||
BroadwellV4 CHIP = "Broadwell-v4" // Intel Core Processor (Broadwell, no TSX, IBRS)
|
||||
CascadelakeServer CHIP = "Cascadelake-Server" // (alias configured by machine type)
|
||||
CascadelakeServerNoTSX CHIP = "Cascadelake-Server-noTSX" // (alias of Cascadelake-Server-v3)
|
||||
CascadelakeServerV1 CHIP = "Cascadelake-Server-v1" // Intel Xeon Processor (Cascadelake)
|
||||
CascadelakeServerV2 CHIP = "Cascadelake-Server-v2" // Intel Xeon Processor (Cascadelake) [ARCH_CAPABILITIES]
|
||||
CascadelakeServerV3 CHIP = "Cascadelake-Server-v3" // Intel Xeon Processor (Cascadelake) [ARCH_CAPABILITIES, no TSX]
|
||||
CascadelakeServerV4 CHIP = "Cascadelake-Server-v4" // Intel Xeon Processor (Cascadelake) [ARCH_CAPABILITIES, EPT switching, no TSX]
|
||||
CascadelakeServerV5 CHIP = "Cascadelake-Server-v5" // Intel Xeon Processor (Cascadelake) [ARCH_CAPABILITIES, EPT switching, XSAVES, no TSX]
|
||||
ClearwaterForest CHIP = "ClearwaterForest" // (alias configured by machine type)
|
||||
ClearwaterForestV1 CHIP = "ClearwaterForest-v1" // Intel Xeon Processor (ClearwaterForest)
|
||||
Conroe CHIP = "Conroe" // (alias configured by machine type)
|
||||
ConroeV1 CHIP = "Conroe-v1" // Intel Celeron_4x0 (Conroe/Merom Class Core 2)
|
||||
Cooperlake CHIP = "Cooperlake" // (alias configured by machine type)
|
||||
CooperlakeV1 CHIP = "Cooperlake-v1" // Intel Xeon Processor (Cooperlake)
|
||||
CooperlakeV2 CHIP = "Cooperlake-v2" // Intel Xeon Processor (Cooperlake) [XSAVES]
|
||||
Denverton CHIP = "Denverton" // (alias configured by machine type)
|
||||
DenvertonV1 CHIP = "Denverton-v1" // Intel Atom Processor (Denverton)
|
||||
DenvertonV2 CHIP = "Denverton-v2" // Intel Atom Processor (Denverton) [no MPX, no MONITOR]
|
||||
DenvertonV3 CHIP = "Denverton-v3" // Intel Atom Processor (Denverton) [XSAVES, no MPX, no MONITOR]
|
||||
Dhyana CHIP = "Dhyana" // (alias configured by machine type)
|
||||
DhyanaV1 CHIP = "Dhyana-v1" // Hygon Dhyana Processor
|
||||
DhyanaV2 CHIP = "Dhyana-v2" // Hygon Dhyana Processor [XSAVES]
|
||||
EPYC CHIP = "EPYC" // (alias configured by machine type)
|
||||
EPYCGenoa CHIP = "EPYC-Genoa" // (alias configured by machine type)
|
||||
EPYCGenoaV1 CHIP = "EPYC-Genoa-v1" // AMD EPYC-Genoa Processor
|
||||
EPYCIBPB CHIP = "EPYC-IBPB" // (alias of EPYC-v2)
|
||||
EPYCMilan CHIP = "EPYC-Milan" // (alias configured by machine type)
|
||||
EPYCMilanV1 CHIP = "EPYC-Milan-v1" // AMD EPYC-Milan Processor
|
||||
EPYCMilanV2 CHIP = "EPYC-Milan-v2" // AMD EPYC-Milan-v2 Processor
|
||||
EPYCRome CHIP = "EPYC-Rome" // (alias configured by machine type)
|
||||
EPYCRomeV1 CHIP = "EPYC-Rome-v1" // AMD EPYC-Rome Processor
|
||||
EPYCRomeV2 CHIP = "EPYC-Rome-v2" // AMD EPYC-Rome Processor
|
||||
EPYCRomeV3 CHIP = "EPYC-Rome-v3" // AMD EPYC-Rome-v3 Processor
|
||||
EPYCRomeV4 CHIP = "EPYC-Rome-v4" // AMD EPYC-Rome-v4 Processor (no XSAVES)
|
||||
EPYCV1 CHIP = "EPYC-v1" // AMD EPYC Processor
|
||||
EPYCV2 CHIP = "EPYC-v2" // AMD EPYC Processor (with IBPB)
|
||||
EPYCV3 CHIP = "EPYC-v3" // AMD EPYC Processor
|
||||
EPYCV4 CHIP = "EPYC-v4" // AMD EPYC-v4 Processor
|
||||
GraniteRapids CHIP = "GraniteRapids" // (alias configured by machine type)
|
||||
GraniteRapidsV1 CHIP = "GraniteRapids-v1" // Intel Xeon Processor (GraniteRapids)
|
||||
GraniteRapidsV2 CHIP = "GraniteRapids-v2" // Intel Xeon Processor (GraniteRapids)
|
||||
Haswell CHIP = "Haswell" // (alias configured by machine type)
|
||||
HaswellIBRS CHIP = "Haswell-IBRS" // (alias of Haswell-v3)
|
||||
HaswellNoTSX CHIP = "Haswell-noTSX" // (alias of Haswell-v2)
|
||||
HaswellNoTSXIBRS CHIP = "Haswell-noTSX-IBRS" // (alias of Haswell-v4)
|
||||
HaswellV1 CHIP = "Haswell-v1" // Intel Core Processor (Haswell)
|
||||
HaswellV2 CHIP = "Haswell-v2" // Intel Core Processor (Haswell, no TSX)
|
||||
HaswellV3 CHIP = "Haswell-v3" // Intel Core Processor (Haswell, IBRS)
|
||||
HaswellV4 CHIP = "Haswell-v4" // Intel Core Processor (Haswell, no TSX, IBRS)
|
||||
IcelakeServer CHIP = "Icelake-Server" // (alias configured by machine type)
|
||||
IcelakeServernoTSX CHIP = "Icelake-Server-noTSX" // (alias of Icelake-Server-v2)
|
||||
IcelakeServerV1 CHIP = "Icelake-Server-v1" // Intel Xeon Processor (Icelake)
|
||||
IcelakeServerV2 CHIP = "Icelake-Server-v2" // Intel Xeon Processor (Icelake) [no TSX]
|
||||
IcelakeServerV3 CHIP = "Icelake-Server-v3" // Intel Xeon Processor (Icelake)
|
||||
IcelakeServerV4 CHIP = "Icelake-Server-v4" // Intel Xeon Processor (Icelake)
|
||||
IcelakeServerV5 CHIP = "Icelake-Server-v5" // Intel Xeon Processor (Icelake) [XSAVES]
|
||||
IcelakeServerV6 CHIP = "Icelake-Server-v6" // Intel Xeon Processor (Icelake) [5-level EPT]
|
||||
IcelakeServerV7 CHIP = "Icelake-Server-v7" // Intel Xeon Processor (Icelake) [TSX, taa-no]
|
||||
IvyBridge CHIP = "IvyBridge" // (alias configured by machine type)
|
||||
IvyBridgeIBRS CHIP = "IvyBridge-IBRS" // (alias of IvyBridge-v2)
|
||||
IvyBridgeV1 CHIP = "IvyBridge-v1" // Intel Xeon E3-12xx v2 (Ivy Bridge)
|
||||
IvyBridgeV2 CHIP = "IvyBridge-v2" // Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS)
|
||||
KnightsMill CHIP = "KnightsMill" // (alias configured by machine type)
|
||||
KnightsMillV1 CHIP = "KnightsMill-v1" // Intel Xeon Phi Processor (Knights Mill)
|
||||
Nehalem CHIP = "Nehalem" // (alias configured by machine type)
|
||||
NehalemIBRS CHIP = "Nehalem-IBRS" // (alias of Nehalem-v2)
|
||||
NehalemV1 CHIP = "Nehalem-v1" // Intel Core i7 9xx (Nehalem Class Core i7)
|
||||
NehalemV2 CHIP = "Nehalem-v2" // Intel Core i7 9xx (Nehalem Core i7, IBRS update)
|
||||
OpteronG1 CHIP = "Opteron-G1" // (alias configured by machine type)
|
||||
OpteronG1V1 CHIP = "Opteron_G1-v1" // AMD Opteron 240 (Gen 1 Class Opteron)
|
||||
OpteronG2 CHIP = "Opteron_G2" // (alias configured by machine type)
|
||||
OpteronG2V1 CHIP = "Opteron_G2-v1" // AMD Opteron 22xx (Gen 2 Class Opteron)
|
||||
OpteronG3 CHIP = "Opteron_G3" // (alias configured by machine type)
|
||||
OpteronG3V1 CHIP = "Opteron_G3-v1" // AMD Opteron 23xx (Gen 3 Class Opteron)
|
||||
OpteronG4 CHIP = "Opteron_G4" // (alias configured by machine type)
|
||||
OpteronG4V1 CHIP = "Opteron_G4-v1" // AMD Opteron 62xx class CPU
|
||||
OpteronG5 CHIP = "Opteron_G5" // (alias configured by machine type)
|
||||
OpteronG5V1 CHIP = "Opteron_G5-v1" // AMD Opteron 63xx class CPU
|
||||
Penryn CHIP = "Penryn" // (alias configured by machine type)
|
||||
PenrynV1 CHIP = "Penryn-v1" // Intel Core 2 Duo P9xxx (Penryn Class Core 2)
|
||||
SandyBridge CHIP = "SandyBridge" // (alias configured by machine type)
|
||||
SandyBridgeIBRS CHIP = "SandyBridge-IBRS" // (alias of SandyBridge-v2)
|
||||
SandyBridgeV1 CHIP = "SandyBridge-v1" // Intel Xeon E312xx (Sandy Bridge)
|
||||
SandyBridgeV2 CHIP = "SandyBridge-v2" // Intel Xeon E312xx (Sandy Bridge, IBRS update)
|
||||
SapphireRapids CHIP = "SapphireRapids" // (alias configured by machine type)
|
||||
SapphireRapidsV1 CHIP = "SapphireRapids-v1" // Intel Xeon Processor (SapphireRapids)
|
||||
SapphireRapidsV2 CHIP = "SapphireRapids-v2" // Intel Xeon Processor (SapphireRapids)
|
||||
SapphireRapidsV3 CHIP = "SapphireRapids-v3" // Intel Xeon Processor (SapphireRapids)
|
||||
SierraForest CHIP = "SierraForest" // (alias configured by machine type)
|
||||
SierraForestV1 CHIP = "SierraForest-v1" // Intel Xeon Processor (SierraForest)
|
||||
SierraForestV2 CHIP = "SierraForest-v2" // Intel Xeon Processor (SierraForest)
|
||||
SkylakeClient CHIP = "Skylake-Client" // (alias configured by machine type)
|
||||
SkylakeClientIBRS CHIP = "Skylake-Client-IBRS" // (alias of Skylake-Client-v2)
|
||||
SkylakeClientNoTSXIBRS CHIP = "Skylake-Client-noTSX-IBRS" // (alias of Skylake-Client-v3)
|
||||
SkylakeClientV1 CHIP = "Skylake-Client-v1" // Intel Core Processor (Skylake)
|
||||
SkylakeClientV2 CHIP = "Skylake-Client-v2" // Intel Core Processor (Skylake, IBRS)
|
||||
SkylakeClientV3 CHIP = "Skylake-Client-v3" // Intel Core Processor (Skylake, IBRS, no TSX)
|
||||
SkylakeClientV4 CHIP = "Skylake-Client-v4" // Intel Core Processor (Skylake, IBRS, no TSX) [IBRS, XSAVES, no TSX]
|
||||
SkylakeServer CHIP = "Skylake-Server" // (alias configured by machine type)
|
||||
SkylakeServerIBRS CHIP = "Skylake-Server-IBRS" // (alias of Skylake-Server-v2)
|
||||
SkylakeServerNoTSXIBRS CHIP = "Skylake-Server-noTSX-IBRS" // (alias of Skylake-Server-v3)
|
||||
SkylakeServerV1 CHIP = "Skylake-Server-v1" // Intel Xeon Processor (Skylake)
|
||||
SkylakeServerV2 CHIP = "Skylake-Server-v2" // Intel Xeon Processor (Skylake, IBRS)
|
||||
SkylakeServerV3 CHIP = "Skylake-Server-v3" // Intel Xeon Processor (Skylake, IBRS, no TSX)
|
||||
SkylakeServerV4 CHIP = "Skylake-Server-v4" // Intel Xeon Processor (Skylake, IBRS, no TSX) [IBRS, EPT switching, no TSX]
|
||||
SkylakeServerV5 CHIP = "Skylake-Server-v5" // Intel Xeon Processor (Skylake, IBRS, no TSX) [IBRS, XSAVES, EPT switching, no TSX]
|
||||
Snowridge CHIP = "Snowridge" // (alias configured by machine type)
|
||||
SnowridgeV1 CHIP = "Snowridge-v1" // Intel Atom Processor (SnowRidge)
|
||||
SnowridgeV2 CHIP = "Snowridge-v2" // Intel Atom Processor (Snowridge, no MPX)
|
||||
SnowridgeV3 CHIP = "Snowridge-v3" // Intel Atom Processor (Snowridge, no MPX) [XSAVES, no MPX]
|
||||
SnowridgeV4 CHIP = "Snowridge-v4" // Intel Atom Processor (Snowridge, no MPX) [no split lock detect, no core-capability]
|
||||
Westmere CHIP = "Westmere" // (alias configured by machine type)
|
||||
WestmereIBRS CHIP = "Westmere-IBRS" // (alias of Westmere-v2)
|
||||
WestmereV1 CHIP = "Westmere-v1" // Westmere E56xx/L56xx/X56xx (Nehalem-C)
|
||||
WestmereV2 CHIP = "Westmere-v2" // Westmere E56xx/L56xx/X56xx (IBRS update)
|
||||
Athlon CHIP = "athlon" // (alias configured by machine type)
|
||||
AthlonV1 CHIP = "athlon-v1" // QEMU Virtual CPU version 2.5+
|
||||
Core2duo CHIP = "core2duo" // (alias configured by machine type)
|
||||
Core2duoV1 CHIP = "core2duo-v1" // Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz
|
||||
Coreduo CHIP = "coreduo" // (alias configured by machine type)
|
||||
CoreduoV1 CHIP = "coreduo-v1" // Genuine Intel(R) CPU T2600 @ 2.16GHz
|
||||
Kvm32 CHIP = "kvm32" // (alias configured by machine type)
|
||||
Kvm32V1 CHIP = "kvm32-v1" // Common 32-bit KVM processor
|
||||
Kvm64 CHIP = "kvm64" // (alias configured by machine type)
|
||||
Kvm64V1 CHIP = "kvm64-v1" // Common KVM processor
|
||||
N270 CHIP = "n270" // (alias configured by machine type)
|
||||
N270V1 CHIP = "n270-v1" // Intel(R) Atom(TM) CPU N270 @ 1.60GHz
|
||||
Pentium CHIP = "pentium" // (alias configured by machine type)
|
||||
PentiumV1 CHIP = "pentium-v1" // Intel(R) Pentium(R) CPU E3600 @ 2.40GHz
|
||||
Pentium2 CHIP = "pentium2" // (alias configured by machine type)
|
||||
Pentium2V1 CHIP = "pentium2-v1" // Intel(R) Pentium(R) CPU E3600 @ 2.40GHz
|
||||
Pentium3 CHIP = "pentium3" // (alias configured by machine type)
|
||||
Pentium3V1 CHIP = "pentium3-v1" // Intel(R) Pentium(R) CPU E3600 @ 2.40GHz
|
||||
Phenom CHIP = "phenom" // (alias configured by machine type)
|
||||
PhenomV1 CHIP = "phenom-v1" // AMD Phenom(tm) 9550 Quad-Core Processor
|
||||
Qqemu32 CHIP = "qemu32" // (alias configured by machine type)
|
||||
Qemu32V1 CHIP = "qemu32-v1" // QEMU Virtual CPU version 2.5+
|
||||
Qemu64 CHIP = "qemu64" // (alias configured by machine type)
|
||||
Qemu64V1 CHIP = "qemu64-v1" // QEMU Virtual CPU version 2.5+
|
||||
Bbase CHIP = "base" // base CPU model type with no features enabled
|
||||
Max CHIP = "max" // Enables all features supported by the accelerator in the current host
|
||||
|
||||
C3Dnow CPUID = "3dnow"
|
||||
C3Dnowext CPUID = "3dnowext"
|
||||
C3Dnowprefetch CPUID = "3dnowprefetch"
|
||||
Abm CPUID = "abm"
|
||||
Ace2 CPUID = "ace2"
|
||||
Ace2En CPUID = "ace2-en"
|
||||
Acpi CPUID = "acpi"
|
||||
Adx CPUID = "adx"
|
||||
Aes CPUID = "aes"
|
||||
AmdNoSsb CPUID = "amd-no-ssb"
|
||||
AmdPsfd CPUID = "amd-psfd"
|
||||
AmdSsbd CPUID = "amd-ssbd"
|
||||
AmdStibp CPUID = "amd-stibp"
|
||||
AmxBf16 CPUID = "amx-bf16"
|
||||
AmxComplex CPUID = "amx-complex"
|
||||
AmxFp16 CPUID = "amx-fp16"
|
||||
AmxInt8 CPUID = "amx-int8"
|
||||
AmxTile CPUID = "amx-tile"
|
||||
Apic CPUID = "apic"
|
||||
Arat CPUID = "arat"
|
||||
ArchCapabilities CPUID = "arch-capabilities"
|
||||
ArchLbr CPUID = "arch-lbr"
|
||||
AutoIbrs CPUID = "auto-ibrs"
|
||||
Avic CPUID = "avic"
|
||||
Avx CPUID = "avx"
|
||||
AvxIfma CPUID = "avx-ifma"
|
||||
AvxNeConvert CPUID = "avx-ne-convert"
|
||||
AvxVnni CPUID = "avx-vnni"
|
||||
AvxVnniInt16 CPUID = "avx-vnni-int16"
|
||||
AvxVnniInt8 CPUID = "avx-vnni-int8"
|
||||
Avx10 CPUID = "avx10"
|
||||
Avx10128 CPUID = "avx10-128"
|
||||
Avx10256 CPUID = "avx10-256"
|
||||
Avx10512 CPUID = "avx10-512"
|
||||
Avx2 CPUID = "avx2"
|
||||
Avx5124Fmaps CPUID = "avx512-4fmaps"
|
||||
Avx5124Vnniw CPUID = "avx512-4vnniw"
|
||||
Avx512Bf16 CPUID = "avx512-bf16"
|
||||
Avx512Fp16 CPUID = "avx512-fp16"
|
||||
Avx512Vp2intersect CPUID = "avx512-vp2intersect"
|
||||
Avx512Vpopcntdq CPUID = "avx512-vpopcntdq"
|
||||
Avx512bitalg CPUID = "avx512bitalg"
|
||||
Avx512bw CPUID = "avx512bw"
|
||||
Avx512cd CPUID = "avx512cd"
|
||||
Avx512dq CPUID = "avx512dq"
|
||||
Avx512er CPUID = "avx512er"
|
||||
Avx512f CPUID = "avx512f"
|
||||
Avx512ifma CPUID = "avx512ifma"
|
||||
Avx512pf CPUID = "avx512pf"
|
||||
Avx512vbmi CPUID = "avx512vbmi"
|
||||
Avx512vbmi2 CPUID = "avx512vbmi2"
|
||||
Avx512vl CPUID = "avx512vl"
|
||||
Avx512vnni CPUID = "avx512vnni"
|
||||
BhiCtrl CPUID = "bhi-ctrl"
|
||||
BhiNo CPUID = "bhi-no"
|
||||
Bmi1 CPUID = "bmi1"
|
||||
Bmi2 CPUID = "bmi2"
|
||||
BusLockDetect CPUID = "bus-lock-detect"
|
||||
Cid CPUID = "cid"
|
||||
Cldemote CPUID = "cldemote"
|
||||
Clflush CPUID = "clflush"
|
||||
Clflushopt CPUID = "clflushopt"
|
||||
Clwb CPUID = "clwb"
|
||||
Clzero CPUID = "clzero"
|
||||
Cmov CPUID = "cmov"
|
||||
CmpLegacy CPUID = "cmp-legacy"
|
||||
Cmpccxadd CPUID = "cmpccxadd"
|
||||
CoreCapability CPUID = "core-capability"
|
||||
Cr8legacy CPUID = "cr8legacy"
|
||||
Cx16 CPUID = "cx16"
|
||||
Cx8 CPUID = "cx8"
|
||||
Dca CPUID = "dca"
|
||||
DdpdU CPUID = "ddpd-u"
|
||||
De CPUID = "de"
|
||||
Decodeassists CPUID = "decodeassists"
|
||||
Ds CPUID = "ds"
|
||||
DsCpl CPUID = "ds-cpl"
|
||||
Dtes64 CPUID = "dtes64"
|
||||
Eraps CPUID = "eraps"
|
||||
Erms CPUID = "erms"
|
||||
Est CPUID = "est"
|
||||
Extapic CPUID = "extapic"
|
||||
F16c CPUID = "f16c"
|
||||
FbClear CPUID = "fb-clear"
|
||||
FbsdpNo CPUID = "fbsdp-no"
|
||||
FdpExcptnOnly CPUID = "fdp-excptn-only"
|
||||
FlushL1d CPUID = "flush-l1d"
|
||||
Flushbyasid CPUID = "flushbyasid"
|
||||
Fma CPUID = "fma"
|
||||
Fma4 CPUID = "fma4"
|
||||
Fpu CPUID = "fpu"
|
||||
Fred CPUID = "fred"
|
||||
Fsgsbase CPUID = "fsgsbase"
|
||||
Fsrc CPUID = "fsrc"
|
||||
Fsrm CPUID = "fsrm"
|
||||
Fsrs CPUID = "fsrs"
|
||||
FullWidthWrite CPUID = "full-width-write"
|
||||
Fxsr CPUID = "fxsr"
|
||||
FxsrOpt CPUID = "fxsr-opt"
|
||||
Fzrm CPUID = "fzrm"
|
||||
GdsNo CPUID = "gds-no"
|
||||
Gfni CPUID = "gfni"
|
||||
Hle CPUID = "hle"
|
||||
Ht CPUID = "ht"
|
||||
Hypervisor CPUID = "hypervisor"
|
||||
Ia64 CPUID = "ia64"
|
||||
Ibpb CPUID = "ibpb"
|
||||
IbpbBrtype CPUID = "ibpb-brtype"
|
||||
Ibrs CPUID = "ibrs"
|
||||
IbrsAll CPUID = "ibrs-all"
|
||||
Ibs CPUID = "ibs"
|
||||
IntelPsfd CPUID = "intel-psfd"
|
||||
IntelPt CPUID = "intel-pt"
|
||||
IntelPtLip CPUID = "intel-pt-lip"
|
||||
Invpcid CPUID = "invpcid"
|
||||
Invtsc CPUID = "invtsc"
|
||||
IpredCtrl CPUID = "ipred-ctrl"
|
||||
KvmAsyncpf CPUID = "kvm-asyncpf"
|
||||
KvmAsyncpfInt CPUID = "kvm-asyncpf-int"
|
||||
KvmAsyncpfVmexit CPUID = "kvm-asyncpf-vmexit"
|
||||
KvmHintDedicated CPUID = "kvm-hint-dedicated"
|
||||
KvmMmu CPUID = "kvm-mmu"
|
||||
KvmMsiExtDestId CPUID = "kvm-msi-ext-dest-id"
|
||||
KvmNopiodelay CPUID = "kvm-nopiodelay"
|
||||
KvmPollControl CPUID = "kvm-poll-control"
|
||||
KvmPvEoi CPUID = "kvm-pv-eoi"
|
||||
KvmPvIpi CPUID = "kvm-pv-ipi"
|
||||
KvmPvSchedYield CPUID = "kvm-pv-sched-yield"
|
||||
KvmPvTlbFlush CPUID = "kvm-pv-tlb-flush"
|
||||
KvmPvUnhalt CPUID = "kvm-pv-unhalt"
|
||||
KvmStealTime CPUID = "kvm-steal-time"
|
||||
Kvmclock CPUID = "kvmclock"
|
||||
KvmclockStableBit CPUID = "kvmclock-stable-bit"
|
||||
La57 CPUID = "la57"
|
||||
LahfLm CPUID = "lahf-lm"
|
||||
Lam CPUID = "lam"
|
||||
Lbrv CPUID = "lbrv"
|
||||
LfenceAlwaysSerializing CPUID = "lfence-always-serializing"
|
||||
Lkgs CPUID = "lkgs"
|
||||
Lm CPUID = "lm"
|
||||
Lwp CPUID = "lwp"
|
||||
Mca CPUID = "mca"
|
||||
McdtNo CPUID = "mcdt-no"
|
||||
Mce CPUID = "mce"
|
||||
MdClear CPUID = "md-clear"
|
||||
MdsNo CPUID = "mds-no"
|
||||
Misalignsse CPUID = "misalignsse"
|
||||
Mmx CPUID = "mmx"
|
||||
Mmxext CPUID = "mmxext"
|
||||
Monitor CPUID = "monitor"
|
||||
Movbe CPUID = "movbe"
|
||||
Movdir64b CPUID = "movdir64b"
|
||||
Movdiri CPUID = "movdiri"
|
||||
Mpx CPUID = "mpx"
|
||||
Msr CPUID = "msr"
|
||||
Mtrr CPUID = "mtrr"
|
||||
NoNestedDataBp CPUID = "no-nested-data-bp"
|
||||
NodeidMsr CPUID = "nodeid-msr"
|
||||
Npt CPUID = "npt"
|
||||
NripSave CPUID = "nrip-save"
|
||||
NullSelClrBase CPUID = "null-sel-clr-base"
|
||||
Nx CPUID = "nx"
|
||||
Osvw CPUID = "osvw"
|
||||
OverflowRecov CPUID = "overflow-recov"
|
||||
Pae CPUID = "pae"
|
||||
Pat CPUID = "pat"
|
||||
PauseFilter CPUID = "pause-filter"
|
||||
Pbe CPUID = "pbe"
|
||||
PbrsbNo CPUID = "pbrsb-no"
|
||||
Pcid CPUID = "pcid"
|
||||
Pclmulqdq CPUID = "pclmulqdq"
|
||||
Pcommit CPUID = "pcommit"
|
||||
Pdcm CPUID = "pdcm"
|
||||
Pdpe1gb CPUID = "pdpe1gb"
|
||||
PerfctrCore CPUID = "perfctr-core"
|
||||
PerfctrNb CPUID = "perfctr-nb"
|
||||
PerfmonV2 CPUID = "perfmon-v2"
|
||||
Pfthreshold CPUID = "pfthreshold"
|
||||
Pge CPUID = "pge"
|
||||
Phe CPUID = "phe"
|
||||
PheEn CPUID = "phe-en"
|
||||
Pks CPUID = "pks"
|
||||
Pku CPUID = "pku"
|
||||
Pmm CPUID = "pmm"
|
||||
PmmEn CPUID = "pmm-en"
|
||||
Pn CPUID = "pn"
|
||||
Pni CPUID = "pni"
|
||||
Popcnt CPUID = "popcnt"
|
||||
Prefetchiti CPUID = "prefetchiti"
|
||||
PschangeMcNo CPUID = "pschange-mc-no"
|
||||
PsdpNo CPUID = "psdp-no"
|
||||
Pse CPUID = "pse"
|
||||
Pse36 CPUID = "pse36"
|
||||
RdctlNo CPUID = "rdctl-no"
|
||||
Rdpid CPUID = "rdpid"
|
||||
Rdrand CPUID = "rdrand"
|
||||
Rdseed CPUID = "rdseed"
|
||||
Rdtscp CPUID = "rdtscp"
|
||||
RfdsClear CPUID = "rfds-clear"
|
||||
RfdsNo CPUID = "rfds-no"
|
||||
RrsbaCtrl CPUID = "rrsba-ctrl"
|
||||
Rsba CPUID = "rsba"
|
||||
Rtm CPUID = "rtm"
|
||||
SbdrSsdpNo CPUID = "sbdr-ssdp-no"
|
||||
Sbpb CPUID = "sbpb"
|
||||
Sep CPUID = "sep"
|
||||
Serialize CPUID = "serialize"
|
||||
Sgx CPUID = "sgx"
|
||||
SgxAexNotify CPUID = "sgx-aex-notify"
|
||||
SgxDebug CPUID = "sgx-debug"
|
||||
SgxEdeccssa CPUID = "sgx-edeccssa"
|
||||
SgxExinfo CPUID = "sgx-exinfo"
|
||||
SgxKss CPUID = "sgx-kss"
|
||||
SgxMode64 CPUID = "sgx-mode64"
|
||||
SgxProvisionkey CPUID = "sgx-provisionkey"
|
||||
SgxTokenkey CPUID = "sgx-tokenkey"
|
||||
Sgx1 CPUID = "sgx1"
|
||||
Sgx2 CPUID = "sgx2"
|
||||
Sgxlc CPUID = "sgxlc"
|
||||
ShaNi CPUID = "sha-ni"
|
||||
Sha512 CPUID = "sha512"
|
||||
Skinit CPUID = "skinit"
|
||||
SkipL1dflVmentry CPUID = "skip-l1dfl-vmentry"
|
||||
Sm3 CPUID = "sm3"
|
||||
Sm4 CPUID = "sm4"
|
||||
Smap CPUID = "smap"
|
||||
Smep CPUID = "smep"
|
||||
Smx CPUID = "smx"
|
||||
SpecCtrl CPUID = "spec-ctrl"
|
||||
SplitLockDetect CPUID = "split-lock-detect"
|
||||
SrsoNo CPUID = "srso-no"
|
||||
SrsoUserKernelNo CPUID = "srso-user-kernel-no"
|
||||
Ss CPUID = "ss"
|
||||
SsbNo CPUID = "ssb-no"
|
||||
Ssbd CPUID = "ssbd"
|
||||
Sse CPUID = "sse"
|
||||
Sse2 CPUID = "sse2"
|
||||
Sse4_1 CPUID = "sse4.1"
|
||||
Sse4_2 CPUID = "sse4.2"
|
||||
Sse4a CPUID = "sse4a"
|
||||
Ssse3 CPUID = "ssse3"
|
||||
Stibp CPUID = "stibp"
|
||||
StibpAlwaysOn CPUID = "stibp-always-on"
|
||||
Succor CPUID = "succor"
|
||||
Svm CPUID = "svm"
|
||||
SvmLock CPUID = "svm-lock"
|
||||
SvmeAddrChk CPUID = "svme-addr-chk"
|
||||
Syscall CPUID = "syscall"
|
||||
TaaNo CPUID = "taa-no"
|
||||
Tbm CPUID = "tbm"
|
||||
Tce CPUID = "tce"
|
||||
Tm CPUID = "tm"
|
||||
Tm2 CPUID = "tm2"
|
||||
Topoext CPUID = "topoext"
|
||||
Tsc CPUID = "tsc"
|
||||
TscAdjust CPUID = "tsc-adjust"
|
||||
TscDeadline CPUID = "tsc-deadline"
|
||||
TscScale CPUID = "tsc-scale"
|
||||
TsxCtrl CPUID = "tsx-ctrl"
|
||||
TsxLdtrk CPUID = "tsx-ldtrk"
|
||||
Umip CPUID = "umip"
|
||||
VVmsaveVmload CPUID = "v-vmsave-vmload"
|
||||
Vaes CPUID = "vaes"
|
||||
Vgif CPUID = "vgif"
|
||||
VirtSsbd CPUID = "virt-ssbd"
|
||||
VmcbClean CPUID = "vmcb-clean"
|
||||
Vme CPUID = "vme"
|
||||
Vmx CPUID = "vmx"
|
||||
VmxActivityHlt CPUID = "vmx-activity-hlt"
|
||||
VmxActivityShutdown CPUID = "vmx-activity-shutdown"
|
||||
VmxActivityWaitSipi CPUID = "vmx-activity-wait-sipi"
|
||||
VmxAnyErrcode CPUID = "vmx-any-errcode"
|
||||
VmxApicvRegister CPUID = "vmx-apicv-register"
|
||||
VmxApicvVid CPUID = "vmx-apicv-vid"
|
||||
VmxApicvX2apic CPUID = "vmx-apicv-x2apic"
|
||||
VmxApicvXapic CPUID = "vmx-apicv-xapic"
|
||||
VmxCr3LoadNoexit CPUID = "vmx-cr3-load-noexit"
|
||||
VmxCr3StoreNoexit CPUID = "vmx-cr3-store-noexit"
|
||||
VmxCr8LoadExit CPUID = "vmx-cr8-load-exit"
|
||||
VmxCr8StoreExit CPUID = "vmx-cr8-store-exit"
|
||||
VmxDescExit CPUID = "vmx-desc-exit"
|
||||
VmxEnableUserWaitPause CPUID = "vmx-enable-user-wait-pause"
|
||||
VmxEnclsExit CPUID = "vmx-encls-exit"
|
||||
VmxEntryIa32eMode CPUID = "vmx-entry-ia32e-mode"
|
||||
VmxEntryLoadBndcfgs CPUID = "vmx-entry-load-bndcfgs"
|
||||
VmxEntryLoadEfer CPUID = "vmx-entry-load-efer"
|
||||
VmxEntryLoadFred CPUID = "vmx-entry-load-fred"
|
||||
VmxEntryLoadPat CPUID = "vmx-entry-load-pat"
|
||||
VmxEntryLoadPerfGlobalCtrl CPUID = "vmx-entry-load-perf-global-ctrl"
|
||||
VmxEntryLoadPkrs CPUID = "vmx-entry-load-pkrs"
|
||||
VmxEntryLoadRtitCtl CPUID = "vmx-entry-load-rtit-ctl"
|
||||
VmxEntryNoloadDebugctl CPUID = "vmx-entry-noload-debugctl"
|
||||
VmxEpt CPUID = "vmx-ept"
|
||||
VmxEpt1Gb CPUID = "vmx-ept-1gb"
|
||||
VmxEpt2Mb CPUID = "vmx-ept-2mb"
|
||||
VmxEptAdvancedExitinfo CPUID = "vmx-ept-advanced-exitinfo"
|
||||
VmxEptExeconly CPUID = "vmx-ept-execonly"
|
||||
VmxEptad CPUID = "vmx-eptad"
|
||||
VmxEptpSwitching CPUID = "vmx-eptp-switching"
|
||||
VmxExitAckIntr CPUID = "vmx-exit-ack-intr"
|
||||
VmxExitClearBndcfgs CPUID = "vmx-exit-clear-bndcfgs"
|
||||
VmxExitClearRtitCtl CPUID = "vmx-exit-clear-rtit-ctl"
|
||||
VmxExitLoadEfer CPUID = "vmx-exit-load-efer"
|
||||
VmxExitLoadPat CPUID = "vmx-exit-load-pat"
|
||||
VmxExitLoadPerfGlobalCtrl CPUID = "vmx-exit-load-perf-global-ctrl"
|
||||
VmxExitLoadPkrs CPUID = "vmx-exit-load-pkrs"
|
||||
VmxExitNosaveDebugctl CPUID = "vmx-exit-nosave-debugctl"
|
||||
VmxExitSaveEfer CPUID = "vmx-exit-save-efer"
|
||||
VmxExitSavePat CPUID = "vmx-exit-save-pat"
|
||||
VmxExitSavePreemptionTimer CPUID = "vmx-exit-save-preemption-timer"
|
||||
VmxExitSecondaryCtls CPUID = "vmx-exit-secondary-ctls"
|
||||
VmxFlexpriority CPUID = "vmx-flexpriority"
|
||||
VmxHltExit CPUID = "vmx-hlt-exit"
|
||||
VmxInsOuts CPUID = "vmx-ins-outs"
|
||||
VmxIntrExit CPUID = "vmx-intr-exit"
|
||||
VmxInvept CPUID = "vmx-invept"
|
||||
VmxInveptAllContext CPUID = "vmx-invept-all-context"
|
||||
VmxInveptSingleContext CPUID = "vmx-invept-single-context"
|
||||
VmxInveptSingleContextNoglobals CPUID = "vmx-invept-single-context-noglobals"
|
||||
VmxInvlpgExit CPUID = "vmx-invlpg-exit"
|
||||
VmxInvpcidExit CPUID = "vmx-invpcid-exit"
|
||||
VmxInvvpid CPUID = "vmx-invvpid"
|
||||
VmxInvvpidAllContext CPUID = "vmx-invvpid-all-context"
|
||||
VmxInvvpidSingleAddr CPUID = "vmx-invvpid-single-addr"
|
||||
VmxIoBitmap CPUID = "vmx-io-bitmap"
|
||||
VmxIoExit CPUID = "vmx-io-exit"
|
||||
VmxMonitorExit CPUID = "vmx-monitor-exit"
|
||||
VmxMovdrExit CPUID = "vmx-movdr-exit"
|
||||
VmxMsrBitmap CPUID = "vmx-msr-bitmap"
|
||||
VmxMtf CPUID = "vmx-mtf"
|
||||
VmxMwaitExit CPUID = "vmx-mwait-exit"
|
||||
VmxNestedException CPUID = "vmx-nested-exception"
|
||||
VmxNmiExit CPUID = "vmx-nmi-exit"
|
||||
VmxPageWalk4 CPUID = "vmx-page-walk-4"
|
||||
VmxPageWalk5 CPUID = "vmx-page-walk-5"
|
||||
VmxPauseExit CPUID = "vmx-pause-exit"
|
||||
VmxPle CPUID = "vmx-ple"
|
||||
VmxPml CPUID = "vmx-pml"
|
||||
VmxPostedIntr CPUID = "vmx-posted-intr"
|
||||
VmxPreemptionTimer CPUID = "vmx-preemption-timer"
|
||||
VmxRdpmcExit CPUID = "vmx-rdpmc-exit"
|
||||
VmxRdrandExit CPUID = "vmx-rdrand-exit"
|
||||
VmxRdseedExit CPUID = "vmx-rdseed-exit"
|
||||
VmxRdtscExit CPUID = "vmx-rdtsc-exit"
|
||||
VmxRdtscpExit CPUID = "vmx-rdtscp-exit"
|
||||
VmxSecondaryCtls CPUID = "vmx-secondary-ctls"
|
||||
VmxShadowVmcs CPUID = "vmx-shadow-vmcs"
|
||||
VmxStoreLma CPUID = "vmx-store-lma"
|
||||
VmxTrueCtls CPUID = "vmx-true-ctls"
|
||||
VmxTscOffset CPUID = "vmx-tsc-offset"
|
||||
VmxTscScaling CPUID = "vmx-tsc-scaling"
|
||||
VmxUnrestrictedGuest CPUID = "vmx-unrestricted-guest"
|
||||
VmxVintrPending CPUID = "vmx-vintr-pending"
|
||||
VmxVmfunc CPUID = "vmx-vmfunc"
|
||||
VmxVmwriteVmexitFields CPUID = "vmx-vmwrite-vmexit-fields"
|
||||
VmxVnmi CPUID = "vmx-vnmi"
|
||||
VmxVnmiPending CPUID = "vmx-vnmi-pending"
|
||||
VmxVpid CPUID = "vmx-vpid"
|
||||
VmxWbinvdExit CPUID = "vmx-wbinvd-exit"
|
||||
VmxXsaves CPUID = "vmx-xsaves"
|
||||
VmxZeroLenInject CPUID = "vmx-zero-len-inject"
|
||||
Vnmi CPUID = "vnmi"
|
||||
Vpclmulqdq CPUID = "vpclmulqdq"
|
||||
Waitpkg CPUID = "waitpkg"
|
||||
Wbnoinvd CPUID = "wbnoinvd"
|
||||
Wdt CPUID = "wdt"
|
||||
Wrmsrns CPUID = "wrmsrns"
|
||||
X2apic CPUID = "x2apic"
|
||||
Xcrypt CPUID = "xcrypt"
|
||||
XcryptEn CPUID = "xcrypt-en"
|
||||
Xfd CPUID = "xfd"
|
||||
Xgetbv1 CPUID = "xgetbv1"
|
||||
Xop CPUID = "xop"
|
||||
Xsave CPUID = "xsave"
|
||||
Xsavec CPUID = "xsavec"
|
||||
Xsaveerptr CPUID = "xsaveerptr"
|
||||
Xsaveopt CPUID = "xsaveopt"
|
||||
Xsaves CPUID = "xsaves"
|
||||
Xstore CPUID = "xstore"
|
||||
XstoreEn CPUID = "xstore-en"
|
||||
Xtpr CPUID = "xtpr"
|
||||
ZeroFcsFds CPUID = "zero-fcs-fds"
|
||||
)
|
||||
27
pkg/types/disk.go
Normal file
27
pkg/types/disk.go
Normal file
@ -0,0 +1,27 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
type Size string
|
||||
|
||||
var (
|
||||
KB = big.NewInt(1000)
|
||||
KIB = big.NewInt(1024)
|
||||
MB = big.NewInt(1000000)
|
||||
MIB = big.NewInt(1048576)
|
||||
GB = big.NewInt(1000000000)
|
||||
GIB = big.NewInt(1073741824)
|
||||
TB = big.NewInt(1000000000000)
|
||||
TIB = big.NewInt(1099511627776)
|
||||
)
|
||||
|
||||
// Takes a base and a multiplier and returns a human readable size
|
||||
func GetSize(base *big.Int, mul int64) Size {
|
||||
b := humanize.BigBytes(big.NewInt(0).Mul(base, big.NewInt(mul)))
|
||||
return Size(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(b, ".0", ""), " ", ""), "B", ""))
|
||||
}
|
||||
160
pkg/types/machine.go
Normal file
160
pkg/types/machine.go
Normal file
@ -0,0 +1,160 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/rayaman/go-qemu/pkg/types/numa"
|
||||
)
|
||||
|
||||
/*
|
||||
TODO:
|
||||
-add-fd fd=fd,set=set[,opaque=opaque]
|
||||
|
||||
Add 'fd' to fd 'set'
|
||||
|
||||
-set group.id.arg=value
|
||||
|
||||
set <arg> parameter for item <id> of type <group>
|
||||
i.e. -set drive.$id.file=/path/to/image
|
||||
|
||||
-global driver.property=value
|
||||
-global driver=driver,property=property,value=value
|
||||
|
||||
set a global default for a driver property
|
||||
*/
|
||||
type Machine struct {
|
||||
Arch System // The binary we use
|
||||
// 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"`
|
||||
|
||||
// Graphics
|
||||
NoGraphic Flag `json:"nographic,omitempty"`
|
||||
|
||||
// Block devices
|
||||
HardDiskA string `json:"hda,omitempty"`
|
||||
HardDiskB string `json:"hdb,omitempty"`
|
||||
HardDiskC string `json:"hdc,omitempty"`
|
||||
HardDiskD string `json:"hdd,omitempty"`
|
||||
FloppyA string `json:"fda,omitempty"`
|
||||
FloppyB string `json:"fdb,omitempty"`
|
||||
CDROM string `json:"cdrom,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Machine) Expand() string {
|
||||
fields := structs.Fields(m)
|
||||
exp := []string{}
|
||||
for _, field := range fields {
|
||||
tag := strings.ReplaceAll(field.Tag("json"), ",omitempty", "")
|
||||
omit := field.Tag("omit")
|
||||
if tag != "" {
|
||||
if field.Kind() == reflect.Struct || field.Kind() == reflect.Interface && !field.IsZero() {
|
||||
if omit != "" {
|
||||
exp = append(exp, Expand(field.Value()))
|
||||
} else {
|
||||
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()))
|
||||
} else {
|
||||
exp = append(exp, fmt.Sprintf("-%v %v", tag, field.Value()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.ReplaceAll(strings.ReplaceAll(fmt.Sprintf("qemu-system-%v %v", m.Arch, strings.Join(exp, " ")), " flag-on", ""), " ", " ")
|
||||
}
|
||||
|
||||
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", "")
|
||||
omit := field.Tag("omit")
|
||||
if !field.IsZero() || field.Kind() == reflect.Bool || strings.Contains(opt, "id") && field.Kind() != reflect.String {
|
||||
switch value := field.Value().(type) {
|
||||
case bool:
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, SW[value]))
|
||||
case *bool:
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, SW[*value]))
|
||||
case []string:
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, strings.Join(value, "")))
|
||||
case numa.CPUS:
|
||||
if value.Last == 0 {
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, value.First))
|
||||
} else {
|
||||
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))
|
||||
}
|
||||
case []numa.Dist:
|
||||
useSpace = true
|
||||
for _, dist := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(dist))
|
||||
}
|
||||
case []numa.CPU:
|
||||
useSpace = true
|
||||
for _, cpu := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(cpu))
|
||||
}
|
||||
case []numa.HMATLB:
|
||||
useSpace = true
|
||||
for _, hmatlb := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(hmatlb))
|
||||
}
|
||||
case []numa.HMATCache:
|
||||
useSpace = true
|
||||
for _, hmatcache := range value {
|
||||
opts = append(opts, "-numa "+opt+","+Expand(hmatcache))
|
||||
}
|
||||
case Options:
|
||||
opts = append(opts, value.ExpandOptions())
|
||||
case []Drives:
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, strings.Join(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))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
otag := ""
|
||||
if len(tag) > 0 {
|
||||
otag = "-" + tag[0] + " "
|
||||
}
|
||||
if useSpace {
|
||||
return otag + strings.Join(opts, " ")
|
||||
}
|
||||
return otag + strings.Join(opts, ",")
|
||||
}
|
||||
13
pkg/types/memory.go
Normal file
13
pkg/types/memory.go
Normal file
@ -0,0 +1,13 @@
|
||||
package types
|
||||
|
||||
/* Configure guest RAM
|
||||
Note: Some architectures might enforce a specific granularity
|
||||
*/
|
||||
type Memory struct {
|
||||
// Initial amount of guest memory
|
||||
Size uint `json:"size,omitempty"`
|
||||
// Number of hotplug slots (default: none)
|
||||
Slots uint `json:"slots,omitempty"`
|
||||
// Maximum amount of guest memory (default: none)
|
||||
MaxMem uint `json:"maxmem,omitempty"`
|
||||
}
|
||||
59
pkg/types/nic.go
Normal file
59
pkg/types/nic.go
Normal file
@ -0,0 +1,59 @@
|
||||
package types
|
||||
|
||||
type (
|
||||
NICType string
|
||||
)
|
||||
|
||||
const (
|
||||
TAP NICType = "tap"
|
||||
Bridge NICType = "bridge"
|
||||
User NICType = "user"
|
||||
Socket NICType = "socket"
|
||||
)
|
||||
|
||||
type TapOptions struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
IFName string `json:"ifname,omitempty"`
|
||||
}
|
||||
|
||||
func (t *TapOptions) ExpandOptions() string {
|
||||
return Expand(t)
|
||||
}
|
||||
|
||||
type BridgeOptions struct {
|
||||
}
|
||||
|
||||
func (b *BridgeOptions) ExpandOptions() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type UserOptions struct {
|
||||
}
|
||||
|
||||
func (u *UserOptions) ExpandOptions() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type SocketOptions struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
FD string `json:"fd,omitempty"`
|
||||
MCast string `json:"mcast,omitempty"`
|
||||
UDP string `json:"udp,omitempty"`
|
||||
LocalAddress string `json:"localaddr,omitempty"`
|
||||
Listen string `json:"listen,omitempty"`
|
||||
Connect string `json:"connect,omitempty"`
|
||||
}
|
||||
|
||||
func (s *SocketOptions) ExpandOptions() string {
|
||||
return Expand(s)
|
||||
}
|
||||
|
||||
type Options interface {
|
||||
ExpandOptions() string
|
||||
}
|
||||
|
||||
type NIC struct {
|
||||
Type NICType `json:"type,omitempty" omit:"true"`
|
||||
MacAddress string `json:"mac,omitempty"`
|
||||
Options Options `json:"options,omitempty"`
|
||||
}
|
||||
74
pkg/types/numa/numa.go
Normal file
74
pkg/types/numa/numa.go
Normal file
@ -0,0 +1,74 @@
|
||||
package numa
|
||||
|
||||
type (
|
||||
Hierarchy string
|
||||
Latency string
|
||||
Associativity string
|
||||
Policy string
|
||||
)
|
||||
|
||||
const (
|
||||
H_Mem Hierarchy = "memory"
|
||||
H_First Hierarchy = "first-level"
|
||||
H_Second Hierarchy = "second-level"
|
||||
H_Third Hierarchy = "third-level"
|
||||
|
||||
L_Access Latency = "access-latency"
|
||||
L_Read Latency = "read-latency"
|
||||
L_Write Latency = "write-latency"
|
||||
|
||||
A_None Associativity = "none"
|
||||
A_Direct Associativity = "direct"
|
||||
A_Complex Associativity = "complex"
|
||||
|
||||
P_None Policy = "none"
|
||||
P_WriteBack Policy = "write-back"
|
||||
P_WriteThru Policy = "write-thrugh"
|
||||
)
|
||||
|
||||
type CPUS struct {
|
||||
First uint `json:"first,omitempty"`
|
||||
Last uint `json:"last,omitempty"`
|
||||
}
|
||||
type Node struct {
|
||||
Memory uint `json:"mem,omitempty" mexclusive:"memdev"`
|
||||
MemoryDev uint `json:"memdev,omitempty" mexclusive:"mem"`
|
||||
Cpus CPUS `json:"cpus,omitempty"`
|
||||
NodeID uint `json:"nodeid,omitempty"`
|
||||
Initiator uint `json:"initiator,omitempty"`
|
||||
}
|
||||
type CPU struct {
|
||||
NodeID uint `json:"node-id,omitempty"`
|
||||
SocketID uint `json:"socket-id,omitempty"`
|
||||
CoreID uint `json:"core-id,omitempty"`
|
||||
ThreadID uint `json:"thread-id,omitempty"`
|
||||
}
|
||||
|
||||
type HMATLB struct {
|
||||
Initiator uint `json:"initiator,omitempty"`
|
||||
Target uint `json:"target,omitempty"`
|
||||
Hierarchy Hierarchy `json:"hierarchy,omitempty"`
|
||||
DataType Latency `json:"data-type,omitempty"`
|
||||
Latency uint `json:"latency,omitempty"`
|
||||
Bandwidth uint `json:"bandwidth,omitempty"`
|
||||
}
|
||||
type HMATCache struct {
|
||||
NodeID uint `json:"node-id,omitempty"`
|
||||
Size uint `json:"size,omitempty"`
|
||||
Level uint `json:"level,omitempty"`
|
||||
Associativity Associativity `json:"associativity,omitempty"`
|
||||
Policy Policy `json:"policy,omitempty"`
|
||||
Line uint `json:"line,omitempty"`
|
||||
}
|
||||
type Dist struct {
|
||||
Src uint `json:"src,omitempty"`
|
||||
Dst uint `json:"dst,omitempty"`
|
||||
Val uint `json:"val,omitempty"`
|
||||
}
|
||||
type Numa struct {
|
||||
Nodes []Node `json:"node,omitempty"`
|
||||
Dist []Dist `json:"dist,omitempty"`
|
||||
Cpu []CPU `json:"cpu,omitempty"`
|
||||
HMATLB []HMATLB `json:"hmat-lb,omitempty"`
|
||||
HMATCache []HMATCache `json:"hmat-cache,omitempty"`
|
||||
}
|
||||
38
pkg/types/smp.go
Normal file
38
pkg/types/smp.go
Normal file
@ -0,0 +1,38 @@
|
||||
package types
|
||||
|
||||
/*
|
||||
Note: Different machines may have different subsets of the CPU topology
|
||||
parameters supported, so the actual meaning of the supported parameters
|
||||
will vary accordingly. For example, for a machine type that supports a
|
||||
three-level CPU hierarchy of sockets/cores/threads, the parameters will
|
||||
sequentially mean as below:
|
||||
sockets means the number of sockets on the machine board
|
||||
cores means the number of cores in one socket
|
||||
threads means the number of threads in one core
|
||||
For a particular machine type board, an expected CPU topology hierarchy
|
||||
can be defined through the supported sub-option. Unsupported parameters
|
||||
can also be provided in addition to the sub-option, but their values
|
||||
must be set as 1 in the purpose of correct parsing.
|
||||
*/
|
||||
type SMP struct {
|
||||
// The number of initial CPUs
|
||||
Cpus uint `json:"cpus,omitempty"`
|
||||
// Maximum number of total CPUs, including offline CPUs for hotplug, etc
|
||||
MaxCpus uint `json:"maxcpus,omitempty"`
|
||||
// Number of drawers on the machine board
|
||||
Drawers uint `json:"drawers,omitempty"`
|
||||
// Number of books in one drawer
|
||||
Books uint `json:"books,omitempty"`
|
||||
// Number of sockets in one book
|
||||
Sockets uint `json:"sockets,omitempty"`
|
||||
// Number of dies in one socket
|
||||
Dies uint `json:"dies,omitempty"`
|
||||
// Number of clusters in one die
|
||||
Clusters uint `json:"clusters,omitempty"`
|
||||
// Number of modules in one cluster
|
||||
Modules uint `json:"modules,omitempty"`
|
||||
// Number of cores in one module
|
||||
Cores uint `json:"cores,omitempty"`
|
||||
// Number of threads in one core
|
||||
Threads uint `json:"threads,omitempty"`
|
||||
}
|
||||
126
pkg/types/types.go
Normal file
126
pkg/types/types.go
Normal file
@ -0,0 +1,126 @@
|
||||
package types
|
||||
|
||||
import "fmt"
|
||||
|
||||
type (
|
||||
Preallocation string
|
||||
Compat string
|
||||
CompressionType string
|
||||
Format string
|
||||
System string
|
||||
Accelerator string
|
||||
VMExit string
|
||||
Thread string
|
||||
KernelIrqchip string
|
||||
Flag string
|
||||
)
|
||||
|
||||
// converts bool to on/off format
|
||||
var SW = map[bool]string{
|
||||
true: "on",
|
||||
false: "off",
|
||||
}
|
||||
var (
|
||||
On *bool = func(b bool) *bool {
|
||||
return &b
|
||||
}(true)
|
||||
Off *bool = func(b bool) *bool {
|
||||
return &b
|
||||
}(false)
|
||||
)
|
||||
|
||||
type Param interface {
|
||||
Expand() string
|
||||
}
|
||||
|
||||
var register = map[string]any{}
|
||||
|
||||
var (
|
||||
// No pre-allocation
|
||||
OFF Preallocation = "off"
|
||||
// Allocates qcow2 metadata, and it's still a sparse image.
|
||||
METADATA Preallocation = "metadata"
|
||||
// Uses posix_fallocate() to "allocate blocks and marking them as uninitialized", and is relatively faster than writing out zeroes to a file:
|
||||
FALLOC Preallocation = "falloc"
|
||||
// Allocates zeroes and makes a non-sparse image.
|
||||
FULL Preallocation = "full"
|
||||
|
||||
Compat_0_10 Compat = "0.10"
|
||||
Compat_1_1 Compat = "1.1"
|
||||
|
||||
Zlib CompressionType = "zlib"
|
||||
Zstd CompressionType = "zstd"
|
||||
|
||||
AARCH64 System = "aarch64"
|
||||
AARCH64W System = "aarch64w"
|
||||
ALPHA System = "alpha"
|
||||
ALPHAW System = "alphaw"
|
||||
ARM System = "arm"
|
||||
ARMW System = "armw"
|
||||
AVR System = "avr"
|
||||
AVRW System = "avrw"
|
||||
HPPA System = "hppa"
|
||||
HPPAW System = "hppaw"
|
||||
I386 System = "i386"
|
||||
I386W System = "i386w"
|
||||
LOONGARCH64 System = "loongarch64"
|
||||
LOONGARCH64W System = "loongarch64w"
|
||||
M68K System = "m68k"
|
||||
M68KW System = "m68kw"
|
||||
MICROBLAZE System = "microblaze"
|
||||
MICROBLAZEEL System = "microblazeel"
|
||||
MICROBLAZEELW System = "microblazeelw"
|
||||
MICROBLAZEW System = "microblazew"
|
||||
MIPS System = "mips"
|
||||
MIPS64 System = "mips64"
|
||||
MIPS64EL System = "mips64el"
|
||||
MIPS64ELW System = "mips64elw"
|
||||
MIPS64W System = "mips64w"
|
||||
MIPSEL System = "mipsel"
|
||||
MIPSELW System = "mipselw"
|
||||
MIPSW System = "mipsw"
|
||||
OR1K System = "or1k"
|
||||
OR1KW System = "or1kw"
|
||||
PPC System = "ppc"
|
||||
PPC64 System = "ppc64"
|
||||
PPC64W System = "ppc64w"
|
||||
PPCW System = "ppcw"
|
||||
RISCV32 System = "riscv32"
|
||||
RISCV32W System = "riscv32w"
|
||||
RISCV64 System = "riscv64"
|
||||
RISCV64W System = "riscv64w"
|
||||
RX System = "rx"
|
||||
RXW System = "rxw"
|
||||
S390X System = "s390x"
|
||||
S390XW System = "s390xw"
|
||||
SH4 System = "sh4"
|
||||
SH4EB System = "sh4eb"
|
||||
SH4EBW System = "sh4ebw"
|
||||
SH4W System = "sh4w"
|
||||
SPARC System = "sparc"
|
||||
SPARC64 System = "sparc64"
|
||||
SPARC64W System = "sparc64w"
|
||||
SPARCW System = "sparcw"
|
||||
TRICORE System = "tricore"
|
||||
TRICOREW System = "tricorew"
|
||||
X86_64 System = "x86_64"
|
||||
X86_64W System = "x86_64w"
|
||||
XTENSA System = "xtensa"
|
||||
XTENSAEB System = "xtensaeb"
|
||||
XTENSAEBW System = "xtensaebw"
|
||||
XTENSAW System = "xtensaw"
|
||||
|
||||
Set Flag = "flag-on"
|
||||
)
|
||||
|
||||
func GetTypes() map[string]any {
|
||||
return register
|
||||
}
|
||||
|
||||
func RegisterType(t string, i any) error {
|
||||
if _, ok := register[t]; !ok {
|
||||
register[t] = i
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("type already registered")
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user