From 8d40bc255e56cd8a2db0cd9703b68216444394ef Mon Sep 17 00:00:00 2001 From: Adphi Date: Thu, 18 Jun 2026 15:37:31 +0200 Subject: [PATCH] feat: add mac address support to qemu run command Signed-off-by: Adphi --- cmd/d2vm/run/qemu.go | 3 +++ docs/content/reference/d2vm_run_qemu.md | 1 + pkg/qemu/config.go | 7 +++++++ pkg/qemu/qemu.go | 13 ++++++++++--- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/cmd/d2vm/run/qemu.go b/cmd/d2vm/run/qemu.go index 212d7bc..8b00907 100644 --- a/cmd/d2vm/run/qemu.go +++ b/cmd/d2vm/run/qemu.go @@ -32,6 +32,7 @@ var ( qemuCmd string qemuDetached bool networking string + mac string publishFlags MultipleFlag QemuCmd = &cobra.Command{ @@ -80,6 +81,7 @@ func init() { // Networking flags.StringVar(&networking, "networking", qemuNetworkingDefault, "Networking mode. Valid options are 'default', 'user', 'bridge[,name]', tap[,name] and 'none'. 'user' uses QEMUs userspace networking. 'bridge' connects to a preexisting bridge. 'tap' uses a prexisting tap device. 'none' disables networking.`") + flags.StringVar(&mac, "mac", "", "MAC address for the virtual machine") flags.Var(&publishFlags, "publish", "Publish a vm's port(s) to the host (default [])") } @@ -105,6 +107,7 @@ func Qemu(cmd *cobra.Command, args []string) { qemu.WithCPUs(cpus), qemu.WithMemory(mem), qemu.WithNetworking(networking), + qemu.WithMAC(mac), qemu.WithStdin(os.Stdin), qemu.WithStdout(os.Stdout), qemu.WithStderr(os.Stderr), diff --git a/docs/content/reference/d2vm_run_qemu.md b/docs/content/reference/d2vm_run_qemu.md index 51f220e..8a89504 100644 --- a/docs/content/reference/d2vm_run_qemu.md +++ b/docs/content/reference/d2vm_run_qemu.md @@ -17,6 +17,7 @@ d2vm run qemu [options] [image-path] [flags] --disk disk Disk config, may be repeated. [file=]path[,size=1G][,format=qcow2] (default []) --gui Set qemu to use video output instead of stdio -h, --help help for qemu + --mac string MAC address for the virtual machine --mem uint Amount of memory in MB (default 1024) --networking string Networking mode. Valid options are 'default', 'user', 'bridge[,name]', tap[,name] and 'none'. 'user' uses QEMUs userspace networking. 'bridge' connects to a preexisting bridge. 'tap' uses a prexisting tap device. 'none' disables networking.` (default "user") --publish multiple-flag Publish a vm's port(s) to the host (default []) (default A multiple flag is a type of flag that can be repeated any number of times) diff --git a/pkg/qemu/config.go b/pkg/qemu/config.go index 45862e0..5e63fac 100644 --- a/pkg/qemu/config.go +++ b/pkg/qemu/config.go @@ -51,6 +51,7 @@ type config struct { qemuImgPath string publishedPorts []PublishedPort netdevConfig string + mac string stdin io.Reader stdout io.Writer @@ -129,6 +130,12 @@ func WithPublishedPorts(ports ...PublishedPort) Option { } } +func WithMAC(mac string) Option { + return func(c *config) { + c.mac = mac + } +} + func WithStdin(r io.Reader) Option { return func(c *config) { c.stdin = r diff --git a/pkg/qemu/qemu.go b/pkg/qemu/qemu.go index 76acb5d..4f724e5 100644 --- a/pkg/qemu/qemu.go +++ b/pkg/qemu/qemu.go @@ -135,6 +135,14 @@ func Run(ctx context.Context, path string, opts ...Option) error { return fmt.Errorf("Invalid networking mode: %s", netMode[0]) } + if config.mac != "" { + if _, err := net.ParseMAC(config.mac); err != nil { + return fmt.Errorf("Invalid MAC address: %s", config.mac) + } + } else { + config.mac = generateMAC().String() + } + if err := config.discoverBinaries(); err != nil { log.Fatal(err) } @@ -286,11 +294,10 @@ func (c *config) buildQemuCmdline() ([]string, error) { } if c.netdevConfig != "" { - mac := generateMAC() if c.arch == "s390x" { - qemuArgs = append(qemuArgs, "-device", "virtio-net-ccw,netdev=t0,mac="+mac.String()) + qemuArgs = append(qemuArgs, "-device", "virtio-net-ccw,netdev=t0,mac="+c.mac) } else { - qemuArgs = append(qemuArgs, "-device", "virtio-net-pci,netdev=t0,mac="+mac.String()) + qemuArgs = append(qemuArgs, "-device", "virtio-net-pci,netdev=t0,mac="+c.mac) } forwardings, err := buildQemuForwardings(c.publishedPorts) if err != nil {