working on multiple nics
This commit is contained in:
parent
c0cabf5c57
commit
b437caaf57
2
go.mod
2
go.mod
@ -8,6 +8,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
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
|
||||
@ -25,4 +26,5 @@ require (
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/crypto v0.6.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
5
go.sum
5
go.sum
@ -1,6 +1,8 @@
|
||||
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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/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=
|
||||
@ -8,6 +10,7 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
|
||||
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/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
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=
|
||||
@ -81,3 +84,5 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
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=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
||||
19
machine.yaml
Normal file
19
machine.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
Arch: x86_64
|
||||
accel:
|
||||
accel: "whpx\r"
|
||||
boot:
|
||||
menu: false
|
||||
order:
|
||||
- c
|
||||
hda: ./imgs/UbuntuTest.img
|
||||
m:
|
||||
size: 4096
|
||||
nic:
|
||||
options:
|
||||
tap:
|
||||
ifname: qemu-tap
|
||||
type: tap
|
||||
nographic: flag-on
|
||||
numa: {}
|
||||
smp:
|
||||
cpus: 4
|
||||
36
main.go
36
main.go
@ -28,6 +28,8 @@ import (
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/smp"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
type Credentials struct {
|
||||
@ -78,7 +80,6 @@ func StartMachine(machine system.Machine) *Controller {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
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
|
||||
@ -137,17 +138,44 @@ func main() {
|
||||
Size: 4096,
|
||||
},
|
||||
Accel: accel.Accel{
|
||||
Accelerator: accel.WHPX,
|
||||
Accelerator: accel.GetAccelerator(arch.X86_64),
|
||||
},
|
||||
Nic: nic.NIC{
|
||||
Type: nic.TAP,
|
||||
Options: &nic.TapOptions{
|
||||
IFName: "qemu-tap",
|
||||
Options: nic.Options{
|
||||
Tap: &nic.TapOptions{
|
||||
IFName: "qemu-tap",
|
||||
},
|
||||
},
|
||||
},
|
||||
NoGraphic: types.Set,
|
||||
HardDiskA: `./imgs/UbuntuTest.img`,
|
||||
}
|
||||
|
||||
data, err := yaml.Marshal(machine)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Write data to a file
|
||||
err = os.WriteFile("machine.yaml", data, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
data, err = os.ReadFile("machine.yaml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
mac := system.Machine{}
|
||||
err = yaml.Unmarshal(data, &mac)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(machine.Expand())
|
||||
// fmt.Println(mac.Expand())
|
||||
|
||||
fmt.Println(accel.GetAccelerator(arch.X86_64))
|
||||
os.Exit(0)
|
||||
ctrl := StartMachine(machine)
|
||||
|
||||
fmt.Println("Press enter to stop machine")
|
||||
|
||||
23
pkg/utils/utils.go
Normal file
23
pkg/utils/utils.go
Normal file
@ -0,0 +1,23 @@
|
||||
package utils
|
||||
|
||||
import "net"
|
||||
|
||||
func GetFreePort() (int, error) {
|
||||
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
l, err := net.ListenTCP("tcp", addr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer l.Close()
|
||||
return l.Addr().(*net.TCPAddr).Port, nil
|
||||
}
|
||||
|
||||
// converts bool to on/off format
|
||||
var SW = map[bool]string{
|
||||
true: "on",
|
||||
false: "off",
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -8,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/abdfnx/gosh"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/disk"
|
||||
)
|
||||
|
||||
@ -59,3 +61,54 @@ func Create(i Image, size disk.Size, opts ...Options) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Loads a saved image structure 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 structure 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
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types"
|
||||
)
|
||||
|
||||
// Loads a saved image structure 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
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Saves an image structure 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
|
||||
}
|
||||
@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/utils"
|
||||
"github.com/rayaman/go-qemu/pkg/utils"
|
||||
)
|
||||
|
||||
func getOptions(m map[string]string) string {
|
||||
@ -11,11 +11,12 @@ import (
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/arch"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/boot"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/chip"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/helpers"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/keyboard"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/memory"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/nic"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/numa"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/smp"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/utils"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -39,14 +40,15 @@ type Machine struct {
|
||||
// Amount of memory in MB
|
||||
Memory memory.Memory `json:"m,omitempty"`
|
||||
// Number of CPU cores
|
||||
Cores smp.SMP `json:"smp,omitempty"`
|
||||
Cpu chip.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 types.Flag `json:"memory-prealloc,omitempty"`
|
||||
Nic nic.NIC `json:"nic,omitempty"`
|
||||
Cores smp.SMP `json:"smp,omitempty"`
|
||||
Cpu chip.CHIP `json:"cpu,omitempty"`
|
||||
Accel accel.Accel `json:"accel,omitempty"`
|
||||
Boot boot.Boot `json:"boot,omitempty"`
|
||||
Numa numa.Numa `json:"numa,omitempty" omit:"true"` // omit tells the Expand function to leave out the tag name
|
||||
MemoryPath string `json:"memory-path,omitempty"`
|
||||
MemoryPrealloc types.Flag `json:"memory-prealloc,omitempty"`
|
||||
Nic nic.NIC `json:"nic,omitempty"`
|
||||
KeyboardLayout keyboard.Keyboard `json:"k,omitempty"`
|
||||
|
||||
// Graphics
|
||||
NoGraphic types.Flag `json:"nographic,omitempty"`
|
||||
@ -70,9 +72,9 @@ func (m *Machine) Expand() []string {
|
||||
if tag != "" {
|
||||
if field.Kind() == reflect.Struct || field.Kind() == reflect.Interface && !field.IsZero() {
|
||||
if omit != "" {
|
||||
exp = append(exp, utils.Expand(field.Value())...)
|
||||
exp = append(exp, helpers.Expand(field.Value())...)
|
||||
} else {
|
||||
exp = append(exp, utils.Expand(field.Value(), tag)...)
|
||||
exp = append(exp, helpers.Expand(field.Value(), tag)...)
|
||||
}
|
||||
} else {
|
||||
if !field.IsZero() {
|
||||
@ -85,6 +87,6 @@ func (m *Machine) Expand() []string {
|
||||
}
|
||||
}
|
||||
}
|
||||
exp = utils.Remove(exp, "")
|
||||
exp = helpers.Remove(exp, "")
|
||||
return exp
|
||||
}
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
package accel
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/arch"
|
||||
)
|
||||
|
||||
type (
|
||||
VMExit string
|
||||
Accelerator string
|
||||
@ -12,7 +21,6 @@ const (
|
||||
XEN Accelerator = "xen"
|
||||
HVF Accelerator = "hvf"
|
||||
NVMM Accelerator = "nvmm"
|
||||
// Windows
|
||||
WHPX Accelerator = "whpx"
|
||||
TCG Accelerator = "tcg"
|
||||
|
||||
@ -55,3 +63,32 @@ type Accel struct {
|
||||
// KVM device path, default /dev/kvm
|
||||
Device string `json:"device,omitempty"`
|
||||
}
|
||||
|
||||
// GetAccelerator returns an accelerator for the given architecture, if it cannot be found, TCG will be returned
|
||||
func GetAccelerator(a arch.System) Accelerator {
|
||||
cmd := exec.Command(fmt.Sprintf("qemu-system-%v", a), "-accel", "help")
|
||||
|
||||
var stdout bytes.Buffer
|
||||
var stdin bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stdin = &stdin
|
||||
|
||||
err := cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
return TCG
|
||||
}
|
||||
|
||||
data := string(stdout.Bytes())
|
||||
|
||||
list := strings.Split(data, "\n")
|
||||
|
||||
for i := 1; i < len(list); i++ {
|
||||
if strings.Contains(list[i], "tcg") {
|
||||
continue
|
||||
}
|
||||
return Accelerator(list[i])
|
||||
}
|
||||
|
||||
return TCG
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -6,17 +6,12 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/rayaman/go-qemu/pkg/utils"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/boot"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/nic"
|
||||
"github.com/rayaman/go-qemu/pkg/v1/types/numa"
|
||||
)
|
||||
|
||||
// converts bool to on/off format
|
||||
var SW = map[bool]string{
|
||||
true: "on",
|
||||
false: "off",
|
||||
}
|
||||
|
||||
func Remove(s []string, r string) []string {
|
||||
for i, v := range s {
|
||||
if v == r {
|
||||
@ -33,13 +28,14 @@ func Expand(obj any, tag ...string) []string {
|
||||
for _, field := range fields {
|
||||
opt := strings.ReplaceAll(field.Tag("json"), ",omitempty", "")
|
||||
opt = strings.ReplaceAll(opt, "omitempty", "")
|
||||
opt = strings.ReplaceAll(opt, ",inline", "")
|
||||
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]))
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, utils.SW[value]))
|
||||
case *bool:
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, SW[*value]))
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, utils.SW[*value]))
|
||||
case []string:
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, strings.Join(value, "")))
|
||||
case numa.CPUS:
|
||||
35
pkg/v1/types/keyboard/keyboard.go
Normal file
35
pkg/v1/types/keyboard/keyboard.go
Normal file
@ -0,0 +1,35 @@
|
||||
package keyboard
|
||||
|
||||
type (
|
||||
Keyboard string
|
||||
)
|
||||
|
||||
var (
|
||||
En_US Keyboard = "en-us"
|
||||
Fr Keyboard = "fr"
|
||||
Da Keyboard = "da"
|
||||
De Keyboard = "de"
|
||||
It Keyboard = "it"
|
||||
Nl Keyboard = "nl"
|
||||
No Keyboard = "no"
|
||||
Pt Keyboard = "pt"
|
||||
Es Keyboard = "es"
|
||||
Fr_ch Keyboard = "fr-ch"
|
||||
De_ch Keyboard = "de-ch"
|
||||
En_gb Keyboard = "en-gb"
|
||||
Ko Keyboard = "ko"
|
||||
Tw Keyboard = "tw"
|
||||
Ja Keyboard = "ja"
|
||||
Fr_ca Keyboard = "fr-ca"
|
||||
Hu Keyboard = "hu"
|
||||
Pl Keyboard = "pl"
|
||||
Cz Keyboard = "cz"
|
||||
Ru Keyboard = "ru"
|
||||
Lv Keyboard = "lv"
|
||||
Tr Keyboard = "tr"
|
||||
Gr Keyboard = "gr"
|
||||
Ar Keyboard = "ar"
|
||||
Lt Keyboard = "lt"
|
||||
Nl_be Keyboard = "nl-be"
|
||||
Be Keyboard = "be"
|
||||
)
|
||||
@ -1,7 +1,12 @@
|
||||
package nic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/rayaman/go-qemu/pkg/utils"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -23,28 +28,21 @@ type TapOptions struct {
|
||||
}
|
||||
|
||||
func (t *TapOptions) ExpandOptions() []string {
|
||||
opts := []string{}
|
||||
if t.ID != "" {
|
||||
opts = append(opts, "id="+t.ID)
|
||||
}
|
||||
if t.IFName != "" {
|
||||
opts = append(opts, "ifname="+t.IFName)
|
||||
}
|
||||
return []string{"tap," + strings.Join(opts, ",")}
|
||||
return []string{"tap," + strings.Join(expand(t), ",")}
|
||||
}
|
||||
|
||||
type BridgeOptions struct {
|
||||
}
|
||||
|
||||
func (b *BridgeOptions) ExpandOptions() []string {
|
||||
return []string{}
|
||||
return []string{"bridge," + strings.Join(expand(b), ",")}
|
||||
}
|
||||
|
||||
type UserOptions struct {
|
||||
}
|
||||
|
||||
func (u *UserOptions) ExpandOptions() []string {
|
||||
return []string{}
|
||||
return []string{"user," + strings.Join(expand(u), ",")}
|
||||
}
|
||||
|
||||
type SocketOptions struct {
|
||||
@ -52,17 +50,36 @@ type SocketOptions struct {
|
||||
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"`
|
||||
LocalAddress string `json:"localaddr,omitempty"`
|
||||
Connect string `json:"connect,omitempty"`
|
||||
}
|
||||
|
||||
func (s *SocketOptions) ExpandOptions() []string {
|
||||
return []string{}
|
||||
return []string{"socket," + strings.Join(expand(s), ",")}
|
||||
}
|
||||
|
||||
type Options interface {
|
||||
ExpandOptions() []string
|
||||
type Options struct {
|
||||
Tap *TapOptions `json:"tap,omitempty"`
|
||||
Bridge *BridgeOptions `json:"bridge,omitempty"`
|
||||
User *UserOptions `json:"user,omitempty"`
|
||||
Socket *SocketOptions `json:"socket,omitempty"`
|
||||
}
|
||||
|
||||
func (o *Options) ExpandOptions() []string {
|
||||
if o.Tap != nil {
|
||||
return o.Tap.ExpandOptions()
|
||||
}
|
||||
if o.Bridge != nil {
|
||||
return o.Bridge.ExpandOptions()
|
||||
}
|
||||
if o.User != nil {
|
||||
return o.User.ExpandOptions()
|
||||
}
|
||||
if o.Socket != nil {
|
||||
return o.Socket.ExpandOptions()
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
type NIC struct {
|
||||
@ -70,3 +87,31 @@ type NIC struct {
|
||||
MacAddress string `json:"mac,omitempty"`
|
||||
Options Options `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func expand(obj any, tag ...string) []string {
|
||||
opts := []string{}
|
||||
fields := structs.Fields(obj)
|
||||
for _, field := range fields {
|
||||
opt := strings.ReplaceAll(field.Tag("json"), ",omitempty", "")
|
||||
opt = strings.ReplaceAll(opt, "omitempty", "")
|
||||
opt = strings.ReplaceAll(opt, ",inline", "")
|
||||
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, utils.SW[*value]))
|
||||
default:
|
||||
if omit == "" {
|
||||
opts = append(opts, fmt.Sprintf("%v=%v", opt, value))
|
||||
} else if omit == "tag" {
|
||||
opts = append(opts, fmt.Sprintf("%v", value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(tag) > 0 {
|
||||
return []string{"-" + tag[0], strings.Join(opts, ",")}
|
||||
} else {
|
||||
return []string{strings.Join(opts, ",")}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user