From a9148a686a7251126ce3ea16ae72867893134579 Mon Sep 17 00:00:00 2001 From: Arthur Sengileyev Date: Fri, 23 Feb 2024 14:07:13 +0200 Subject: [PATCH] Update Podman build to latest Podman machine 5 --- .github/workflows/prepare-podman-release.yml | 6 +- README.md | 20 +- ...ge-QEMU-netdev-to-Unix-domain-socket.patch | 172 ++++ ...-Unix-domain-socket-support-for-VLAN.patch | 825 ------------------ ...ment-QEMU-Podman-machine-on-Windows.patch} | 89 +- 5 files changed, 244 insertions(+), 868 deletions(-) create mode 100644 patches/podman/0001-Change-QEMU-netdev-to-Unix-domain-socket.patch delete mode 100644 patches/podman/0001-Implement-Unix-domain-socket-support-for-VLAN.patch rename patches/podman/{0002-Enable-QEMU-Podman-machine-on-Windows.patch => 0002-Implement-QEMU-Podman-machine-on-Windows.patch} (58%) diff --git a/.github/workflows/prepare-podman-release.yml b/.github/workflows/prepare-podman-release.yml index 6353500..cadae04 100644 --- a/.github/workflows/prepare-podman-release.yml +++ b/.github/workflows/prepare-podman-release.yml @@ -4,7 +4,7 @@ on: workflow_dispatch env: PODMAN_GITURL: https://github.com/containers/podman.git - PODMAN_SHA: 8df25d705e148460b1c85cbcd653a132ef2d81b5 + PODMAN_SHA: e4719cb7cdf3ef2b0edcaa4c608117f761322aae jobs: build: @@ -53,8 +53,8 @@ jobs: git remote add origin $PODMAN_GITURL git fetch --depth 1 origin $PODMAN_SHA git checkout FETCH_HEAD - patch --binary -l -p 1 < ../patches/podman/0001-Implement-Unix-domain-socket-support-for-VLAN.patch - patch --binary -l -p 1 < ../patches/podman/0002-Enable-QEMU-Podman-machine-on-Windows.patch + patch --binary -l -p 1 < ../patches/podman/0001-Change-QEMU-netdev-to-Unix-domain-socket.patch + patch --binary -l -p 1 < ../patches/podman/0002-Implement-QEMU-Podman-machine-on-Windows.patch - name: "🛠️ Build Podman" working-directory: podman-release diff --git a/README.md b/README.md index 98981f1..88e52ef 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,8 @@ Version `v9.5.0.0` with 1 patch from Powershell OpenSSH fork PRs: #### `Podman` -Version `5.0.0-dev` with 2 patch sets from Podman PRs: -* Implement Unix domain socket support for VLAN https://github.com/containers/podman/pull/17473; -* Enable QEMU Podman machine on Windows https://github.com/containers/podman/pull/18488. +Version `5.0.0-dev` with TBD patch sets from Podman PRs: +* TBD #### `Podman Desktop` @@ -68,7 +67,7 @@ Latest version (or stable later than v0.0.12) is a requirement. Should be instal Starting from version `0.0.6` of qcw it is possible to use with official windows builds of QEMU (if host FS mounts are not needed). -Version `8.2.0` with 3 patch sets from QEMU mailing list: +Version `8.2.1` with 3 patch sets from QEMU mailing list: * hw/9pfs: Add 9pfs support for Windows https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg05533.html; * WHPX: Add support for device backed memory regions https://lists.gnu.org/archive/html/qemu-devel/2022-07/msg04837.html; * Windows installer: keep dependency cache https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg03125.html. @@ -101,6 +100,19 @@ one wants more control over tools version). One will have preconfigured shell la when installation completes. When using `podman-default.bat` one needs to configure machine provider in `%APPDATA%\containers\containers.conf` setting `provider = "qemu"` or `provider = "wsl"` inside `[machine]` section. +**This is needed temporary until it is added to Podman installation itself** + +Add `C:\etc\containers\policy.json` with content +```json +{ + "default": [ + { + "type": "insecureAcceptAnything" + } + ] +} +``` + Then run the Podman machine init command as one would do with all other Podman installations. The catch is to give 2 mandatory config overrides: ```bat diff --git a/patches/podman/0001-Change-QEMU-netdev-to-Unix-domain-socket.patch b/patches/podman/0001-Change-QEMU-netdev-to-Unix-domain-socket.patch new file mode 100644 index 0000000..ce916a4 --- /dev/null +++ b/patches/podman/0001-Change-QEMU-netdev-to-Unix-domain-socket.patch @@ -0,0 +1,172 @@ +From 39e44a802aebb350ffd9c9745b3f38f81588a4c9 Mon Sep 17 00:00:00 2001 +From: Arthur Sengileyev +Date: Fri, 9 Feb 2024 20:30:24 +0200 +Subject: [PATCH 1/2] Change QEMU netdev to Unix domain socket + +This change migrates to new QEMU stream netdev added in 7.2.0. +It also unifies how gvproxy is used in QEMU and AppleHV. + +Signed-off-by: Arthur Sengileyev +--- + pkg/machine/qemu/command/command.go | 13 ++++++- + pkg/machine/qemu/command/qemu_command_test.go | 9 ++++- + pkg/machine/qemu/stubber.go | 39 +++++++++---------- + 3 files changed, 37 insertions(+), 24 deletions(-) + +diff --git a/pkg/machine/qemu/command/command.go b/pkg/machine/qemu/command/command.go +index b795d73b4..55bba3050 100644 +--- a/pkg/machine/qemu/command/command.go ++++ b/pkg/machine/qemu/command/command.go +@@ -52,10 +52,19 @@ func (q *QemuCmd) SetQmpMonitor(monitor Monitor) { + } + + // SetNetwork adds a network device to the machine +-func (q *QemuCmd) SetNetwork() { ++func (q *QemuCmd) SetNetwork(vlanSocket *define.VMFile) error { + // Right now the mac address is hardcoded so that the host networking gives it a specific IP address. This is + // why we can only run one vm at a time right now +- *q = append(*q, "-netdev", "socket,id=vlan,fd=3", "-device", "virtio-net-pci,netdev=vlan,mac=5a:94:ef:e4:0c:ee") ++ if vlanSocket == nil { ++ return errors.New("vlanSocket is undefined") ++ } ++ *q = append(*q, "-netdev", socketVlanNetdev(vlanSocket.GetPath())) ++ *q = append(*q, "-device", "virtio-net-pci,netdev=vlan,mac=5a:94:ef:e4:0c:ee") ++ return nil ++} ++ ++func socketVlanNetdev(path string) string { ++ return fmt.Sprintf("stream,id=vlan,server=off,addr.type=unix,addr.path=%s", path) + } + + // SetNetwork adds a network device to the machine +diff --git a/pkg/machine/qemu/command/qemu_command_test.go b/pkg/machine/qemu/command/qemu_command_test.go +index eae29bd52..ee329db22 100644 +--- a/pkg/machine/qemu/command/qemu_command_test.go ++++ b/pkg/machine/qemu/command/qemu_command_test.go +@@ -21,6 +21,9 @@ func TestQemuCmd(t *testing.T) { + readySocket, err := define.NewMachineFile(t.TempDir()+"readySocket.sock", nil) + assert.NoError(t, err) + ++ vlanSocket, err := define.NewMachineFile(t.TempDir()+"vlanSocket.sock", nil) ++ assert.NoError(t, err) ++ + vmPidFile, err := define.NewMachineFile(t.TempDir()+"vmpidfile.pid", nil) + assert.NoError(t, err) + +@@ -32,6 +35,7 @@ func TestQemuCmd(t *testing.T) { + ignPath := ignFile.GetPath() + addrFilePath := machineAddrFile.GetPath() + readySocketPath := readySocket.GetPath() ++ vlanSocketPath := vlanSocket.GetPath() + vmPidFilePath := vmPidFile.GetPath() + bootableImagePath := t.TempDir() + "test-machine_fedora-coreos-38.20230918.2.0-qemu.x86_64.qcow2" + +@@ -40,7 +44,8 @@ func TestQemuCmd(t *testing.T) { + cmd.SetCPUs(4) + cmd.SetIgnitionFile(*ignFile) + cmd.SetQmpMonitor(monitor) +- cmd.SetNetwork() ++ err = cmd.SetNetwork(vlanSocket) ++ assert.NoError(t, err) + cmd.SetSerialPort(*readySocket, *vmPidFile, "test-machine") + cmd.SetVirtfsMount("/tmp/path", "vol10", "none", true) + cmd.SetBootableImage(bootableImagePath) +@@ -52,7 +57,7 @@ func TestQemuCmd(t *testing.T) { + "-smp", "4", + "-fw_cfg", fmt.Sprintf("name=opt/com.coreos/config,file=%s", ignPath), + "-qmp", fmt.Sprintf("unix:%s,server=on,wait=off", addrFilePath), +- "-netdev", "socket,id=vlan,fd=3", ++ "-netdev", socketVlanNetdev(vlanSocketPath), + "-device", "virtio-net-pci,netdev=vlan,mac=5a:94:ef:e4:0c:ee", + "-device", "virtio-serial", + "-chardev", fmt.Sprintf("socket,path=%s,server=on,wait=off,id=atest-machine_ready", readySocketPath), +diff --git a/pkg/machine/qemu/stubber.go b/pkg/machine/qemu/stubber.go +index bcb8803e5..d488402aa 100644 +--- a/pkg/machine/qemu/stubber.go ++++ b/pkg/machine/qemu/stubber.go +@@ -7,7 +7,6 @@ import ( + "bytes" + "errors" + "fmt" +- "net" + "os" + "os/exec" + "path/filepath" +@@ -34,6 +33,11 @@ type QEMUStubber struct { + Command command.QemuCmd + } + ++var ( ++ gvProxyWaitBackoff = 500 * time.Millisecond ++ gvProxyMaxBackoffAttempts = 6 ++) ++ + func (q QEMUStubber) UserModeNetworkEnabled(*vmconfigs.MachineConfig) bool { + return true + } +@@ -70,7 +74,13 @@ func (q *QEMUStubber) setQEMUCommandLine(mc *vmconfigs.MachineConfig) error { + q.Command.SetCPUs(mc.Resources.CPUs) + q.Command.SetIgnitionFile(*ignitionFile) + q.Command.SetQmpMonitor(mc.QEMUHypervisor.QMPMonitor) +- q.Command.SetNetwork() ++ gvProxySock, err := mc.GVProxySocket() ++ if err != nil { ++ return err ++ } ++ if err := q.Command.SetNetwork(gvProxySock); err != nil { ++ return err ++ } + q.Command.SetSerialPort(*readySocket, *mc.QEMUHypervisor.QEMUPidPath, mc.Name) + + // Add volumes to qemu command line +@@ -136,9 +146,6 @@ func (q *QEMUStubber) StartVM(mc *vmconfigs.MachineConfig) (func() error, func() + return nil, nil, fmt.Errorf("unable to generate qemu command line: %q", err) + } + +- defaultBackoff := 500 * time.Millisecond +- maxBackoffs := 6 +- + readySocket, err := mc.ReadySocket() + if err != nil { + return nil, nil, err +@@ -149,17 +156,10 @@ func (q *QEMUStubber) StartVM(mc *vmconfigs.MachineConfig) (func() error, func() + return nil, nil, err + } + +- qemuNetdevSockConn, err := sockets.DialSocketWithBackoffs(maxBackoffs, defaultBackoff, gvProxySock.GetPath()) +- if err != nil { +- return nil, nil, fmt.Errorf("failed to connect to gvproxy socket: %w", err) +- } +- defer qemuNetdevSockConn.Close() +- +- fd, err := qemuNetdevSockConn.(*net.UnixConn).File() +- if err != nil { ++ // Wait on gvproxy to be running and aware ++ if err := sockets.WaitForSocketWithBackoffs(gvProxyMaxBackoffAttempts, gvProxyWaitBackoff, gvProxySock.GetPath(), "gvproxy"); err != nil { + return nil, nil, err + } +- defer fd.Close() + + dnr, dnw, err := machine.GetDevNullFiles() + if err != nil { +@@ -184,12 +184,11 @@ func (q *QEMUStubber) StartVM(mc *vmconfigs.MachineConfig) (func() error, func() + + // actually run the command that starts the virtual machine + cmd := &exec.Cmd{ +- Args: cmdLine, +- Path: cmdLine[0], +- Stdin: dnr, +- Stdout: dnw, +- Stderr: stderrBuf, +- ExtraFiles: []*os.File{fd}, ++ Args: cmdLine, ++ Path: cmdLine[0], ++ Stdin: dnr, ++ Stdout: dnw, ++ Stderr: stderrBuf, + } + + if err := runStartVMCommand(cmd); err != nil { +-- +2.43.2 + diff --git a/patches/podman/0001-Implement-Unix-domain-socket-support-for-VLAN.patch b/patches/podman/0001-Implement-Unix-domain-socket-support-for-VLAN.patch deleted file mode 100644 index f60b6ab..0000000 --- a/patches/podman/0001-Implement-Unix-domain-socket-support-for-VLAN.patch +++ /dev/null @@ -1,825 +0,0 @@ -From 5726c7fd4e5f937ef07aa117bca00aa79fc63b0a Mon Sep 17 00:00:00 2001 -From: Arthur Sengileyev -Date: Tue, 26 Sep 2023 14:52:38 +0300 -Subject: [PATCH 1/2] Implement Unix domain socket support for VLAN - -This change adds support for new QEMU stream netdev added in 7.2.0. -It is implemented as an opt-in mode for previously supported -platforms and the only supported mode on Windows. - -Old FD netdev has changes only on podman side. Instead of previously -used QMP socket address, it now has VLAN dedicated socket address to -make both implementations more similar. - -As VLAN socket address has short lifespan (it exists only after -forwarder has been started and before QEMU has finished startup), -it is not promoted to persisted machine settings, but is rather -calculated inside Start method. - -Signed-off-by: Arthur Sengileyev ---- - pkg/machine/e2e/README.md | 15 ++ - pkg/machine/machine_windows.go | 11 + - pkg/machine/qemu/command/command.go | 24 +- - pkg/machine/qemu/command/command_unix.go | 13 ++ - pkg/machine/qemu/command/command_windows.go | 5 + - pkg/machine/qemu/command/qemu_command_test.go | 3 +- - pkg/machine/qemu/config.go | 15 +- - pkg/machine/qemu/machine.go | 209 ++++++++++++------ - pkg/machine/qemu/machine_unix.go | 51 +++-- - pkg/machine/qemu/machine_windows.go | 55 ++++- - pkg/machine/wsl/machine.go | 2 +- - pkg/machine/wsl/util_windows.go | 7 - - 12 files changed, 300 insertions(+), 110 deletions(-) - create mode 100644 pkg/machine/qemu/command/command_unix.go - create mode 100644 pkg/machine/qemu/command/command_windows.go - -diff --git a/pkg/machine/e2e/README.md b/pkg/machine/e2e/README.md -index 5a1e324a2..aab722355 100644 ---- a/pkg/machine/e2e/README.md -+++ b/pkg/machine/e2e/README.md -@@ -36,3 +36,18 @@ Note: To run specific test files, add the test files to the end of the winmake c - 1. `export CONTAINERS_MACHINE_PROVIDER="applehv"` - 1. `export MACHINE_IMAGE="https://fedorapeople.org/groups/podman/testing/applehv/arm64/fedora-coreos-38.20230925.dev.0-applehv.aarch64.raw.gz"` - 1. `make localmachine` (Add `FOCUS_FILE=basic_test.go` to only run basic test) -+ -+### QEMU (fd vlan) -+ -+1. Install QEMU `brew install qemu` -+1. Install Podman (needed to have gvproxy binary) `brew install podman` -+1. `make podman-remote` -+1. `make localmachine` (Add `FOCUS_FILE=basic_test.go` to only run basic test) -+ -+### QEMU (UNIX domain socket vlan) -+ -+1. Install QEMU `brew install qemu` -+1. Install Podman (needed to have gvproxy binary) `brew install podman` -+1. `make podman-remote` -+1. `export CONTAINERS_USE_SOCKET_VLAN=true` -+1. `make localmachine` (Add `FOCUS_FILE=basic_test.go` to only run basic test) -diff --git a/pkg/machine/machine_windows.go b/pkg/machine/machine_windows.go -index 993aeefd4..4136368b9 100644 ---- a/pkg/machine/machine_windows.go -+++ b/pkg/machine/machine_windows.go -@@ -10,6 +10,17 @@ import ( - "github.com/sirupsen/logrus" - ) - -+// nolint // Cleaner to refer to the official OS constant names, and consistent with syscall -+const ( -+ WM_QUIT = 0x12 -+) -+ -+func SendQuit(tid uint32) { -+ user32 := syscall.NewLazyDLL("user32.dll") -+ postMessage := user32.NewProc("PostThreadMessageW") -+ postMessage.Call(uintptr(tid), WM_QUIT, 0, 0) -+} -+ - func GetProcessState(pid int) (active bool, exitCode int) { - const da = syscall.STANDARD_RIGHTS_READ | syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE - handle, err := syscall.OpenProcess(da, false, uint32(pid)) -diff --git a/pkg/machine/qemu/command/command.go b/pkg/machine/qemu/command/command.go -index 3619619ef..2a86bd40e 100644 ---- a/pkg/machine/qemu/command/command.go -+++ b/pkg/machine/qemu/command/command.go -@@ -2,6 +2,7 @@ package command - - import ( - "encoding/base64" -+ "errors" - "fmt" - "os" - "path/filepath" -@@ -14,6 +15,11 @@ import ( - "github.com/containers/podman/v4/pkg/machine/define" - ) - -+const ( -+ FdVlanNetdev = "socket,id=vlan,fd=3" -+ vlanMac = "5a:94:ef:e4:0c:ee" -+) -+ - // QemuCmd is an alias around a string slice to prevent the need to migrate the - // MachineVM struct due to changes - type QemuCmd []string -@@ -47,13 +53,25 @@ func (q *QemuCmd) SetQmpMonitor(monitor Monitor) { - } - - // SetNetwork adds a network device to the machine --func (q *QemuCmd) SetNetwork() { -+func (q *QemuCmd) SetNetwork(vlanSocket *define.VMFile) error { - // Right now the mac address is hardcoded so that the host networking gives it a specific IP address. This is - // why we can only run one vm at a time right now -- *q = append(*q, "-netdev", "socket,id=vlan,fd=3", "-device", "virtio-net-pci,netdev=vlan,mac=5a:94:ef:e4:0c:ee") -+ if UseFdVLan() { -+ *q = append(*q, []string{"-netdev", FdVlanNetdev}...) -+ } else { -+ if vlanSocket == nil { -+ return errors.New("vlanSocket is undefined") -+ } -+ *q = append(*q, []string{"-netdev", socketVlanNetdev(vlanSocket.GetPath())}...) -+ } -+ *q = append(*q, []string{"-device", "virtio-net-pci,netdev=vlan,mac=" + vlanMac}...) -+ return nil -+} -+ -+func socketVlanNetdev(path string) string { -+ return fmt.Sprintf("stream,id=vlan,server=off,addr.type=unix,addr.path=%s", path) - } - --// SetNetwork adds a network device to the machine - func (q *QemuCmd) SetUSBHostPassthrough(usbs []USBConfig) { - if len(usbs) == 0 { - return -diff --git a/pkg/machine/qemu/command/command_unix.go b/pkg/machine/qemu/command/command_unix.go -new file mode 100644 -index 000000000..b05e0ca51 ---- /dev/null -+++ b/pkg/machine/qemu/command/command_unix.go -@@ -0,0 +1,13 @@ -+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd -+// +build darwin dragonfly freebsd linux netbsd openbsd -+ -+package command -+ -+import ( -+ "os" -+ "strings" -+) -+ -+func UseFdVLan() bool { -+ return strings.ToUpper(os.Getenv("CONTAINERS_USE_SOCKET_VLAN")) != "TRUE" -+} -diff --git a/pkg/machine/qemu/command/command_windows.go b/pkg/machine/qemu/command/command_windows.go -new file mode 100644 -index 000000000..9fdea7e3f ---- /dev/null -+++ b/pkg/machine/qemu/command/command_windows.go -@@ -0,0 +1,5 @@ -+package command -+ -+func UseFdVLan() bool { -+ return false -+} -diff --git a/pkg/machine/qemu/command/qemu_command_test.go b/pkg/machine/qemu/command/qemu_command_test.go -index 5cfa6c0d5..bb79b5be4 100644 ---- a/pkg/machine/qemu/command/qemu_command_test.go -+++ b/pkg/machine/qemu/command/qemu_command_test.go -@@ -40,7 +40,8 @@ func TestQemuCmd(t *testing.T) { - cmd.SetCPUs(4) - cmd.SetIgnitionFile(*ignFile) - cmd.SetQmpMonitor(monitor) -- cmd.SetNetwork() -+ err = cmd.SetNetwork(nil) -+ assert.NoError(t, err) - cmd.SetSerialPort(*readySocket, *vmPidFile, "test-machine") - cmd.SetVirtfsMount("/tmp/path", "vol10", "none", true) - cmd.SetBootableImage(bootableImagePath) -diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go -index e15e7b038..a47232fdd 100644 ---- a/pkg/machine/qemu/config.go -+++ b/pkg/machine/qemu/config.go -@@ -61,15 +61,22 @@ func (v *MachineVM) setQMPMonitorSocket() error { - - // setNewMachineCMD configure the CLI command that will be run to create the new - // machine --func (v *MachineVM) setNewMachineCMD(qemuBinary string, cmdOpts *setNewMachineCMDOpts) { -+func (v *MachineVM) setNewMachineCMD(qemuBinary string, cmdOpts *setNewMachineCMDOpts) error { - v.CmdLine = command.NewQemuBuilder(qemuBinary, v.addArchOptions(cmdOpts)) - v.CmdLine.SetMemory(v.Memory) - v.CmdLine.SetCPUs(v.CPUs) - v.CmdLine.SetIgnitionFile(v.IgnitionFile) - v.CmdLine.SetQmpMonitor(v.QMPMonitor) -- v.CmdLine.SetNetwork() -+ vlanSocket, err := machineSocket(v.Name, "vlan", "") -+ if err != nil { -+ return err -+ } -+ if err := v.CmdLine.SetNetwork(vlanSocket); err != nil { -+ return err -+ } - v.CmdLine.SetSerialPort(v.ReadySocket, v.VMPidFilePath, v.Name) - v.CmdLine.SetUSBHostPassthrough(v.USBs) -+ return nil - } - - // NewMachine initializes an instance of a virtual machine based on the qemu -@@ -146,7 +153,9 @@ func (p *QEMUVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, e - - // configure command to run - cmdOpts := setNewMachineCMDOpts{imageDir: dataDir} -- vm.setNewMachineCMD(execPath, &cmdOpts) -+ if err := vm.setNewMachineCMD(execPath, &cmdOpts); err != nil { -+ return nil, err -+ } - return vm, nil - } - -diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go -index 14ab01d79..7db208240 100644 ---- a/pkg/machine/qemu/machine.go -+++ b/pkg/machine/qemu/machine.go -@@ -45,6 +45,10 @@ const ( - MountType9p = "9p" - dockerSock = "/var/run/docker.sock" - dockerConnectTimeout = 5 * time.Second -+ retryCountForStop = 5 -+ fallbackUID = 501 -+ baseBackoff = 500 * time.Millisecond -+ maxStartupBackoffs = 6 - ) - - type MachineVM struct { -@@ -144,6 +148,9 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { - } - - v.UID = os.Getuid() -+ if v.UID == -1 { -+ v.UID = fallbackUID // Used on Windows to match FCOS image -+ } - - // Add location of bootable image - v.CmdLine.SetBootableImage(v.getImageFile()) -@@ -428,20 +435,18 @@ func (v *MachineVM) qemuPid() (int, error) { - logrus.Warnf("Reading QEMU pidfile: %v", err) - return -1, nil - } -- return findProcess(pid) -+ -+ return pingProcess(pid) - } - - // Start executes the qemu command line and forks it - func (v *MachineVM) Start(name string, opts machine.StartOptions) error { - var ( -- conn net.Conn -- err error -- qemuSocketConn net.Conn -+ conn net.Conn -+ err error -+ fd *os.File - ) - -- defaultBackoff := 500 * time.Millisecond -- maxBackoffs := 6 -- - v.lock.Lock() - defer v.lock.Unlock() - -@@ -495,11 +500,6 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error { - logrus.Errorf("machine %q is incompatible with this release of podman and needs to be recreated, starting for recovery only", v.Name) - } - -- forwardSock, forwardState, err := v.startHostNetworking() -- if err != nil { -- return fmt.Errorf("unable to start host networking: %q", err) -- } -- - rtPath, err := getRuntimeDir() - if err != nil { - return err -@@ -513,23 +513,44 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error { - } - } - -- // If the qemusocketpath exists and the vm is off/down, we should rm -- // it before the dial as to avoid a segv -- if err := v.QMPMonitor.Address.Delete(); err != nil { -+ vlanSocket, err := machineSocket(v.Name, "vlan", "") -+ if err != nil { -+ return fmt.Errorf("failed to connect to qemu monitor socket: %w", err) -+ } -+ err = vlanSocket.Delete() -+ if err != nil { - return err - } -+ isFdVlanVM := false -+ for _, c := range v.CmdLine { -+ if c == command.FdVlanNetdev { -+ isFdVlanVM = true -+ } -+ } - -- qemuSocketConn, err = sockets.DialSocketWithBackoffs(maxBackoffs, defaultBackoff, v.QMPMonitor.Address.Path) -+ forwardSock, forwardState, forwarderProcess, err := v.startHostNetworking(vlanSocket) - if err != nil { -- return fmt.Errorf("failed to connect to qemu monitor socket: %w", err) -+ return fmt.Errorf("unable to start host networking: %q", err) - } -- defer qemuSocketConn.Close() - -- fd, err := qemuSocketConn.(*net.UnixConn).File() -- if err != nil { -- return err -+ if isFdVlanVM { -+ qemuSocketConn, err := sockets.DialSocketWithBackoffs(maxStartupBackoffs, baseBackoff, vlanSocket.GetPath()) -+ if err != nil { -+ return err -+ } -+ defer qemuSocketConn.Close() -+ -+ fd, err = qemuSocketConn.(*net.UnixConn).File() -+ if err != nil { -+ return err -+ } -+ defer fd.Close() -+ } else { -+ err := waitForVlanReady(forwarderProcess.Pid, vlanSocket.GetPath()) -+ if err != nil { -+ return err -+ } - } -- defer fd.Close() - - dnr, dnw, err := machine.GetDevNullFiles() - if err != nil { -@@ -538,9 +559,6 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error { - defer dnr.Close() - defer dnw.Close() - -- attr := new(os.ProcAttr) -- files := []*os.File{dnr, dnw, dnw, fd} -- attr.Files = files - cmdLine := v.CmdLine - - cmdLine.SetPropagatedHostEnvs() -@@ -557,12 +575,15 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error { - - // actually run the command that starts the virtual machine - cmd := &exec.Cmd{ -- Args: cmdLine, -- Path: cmdLine[0], -- Stdin: dnr, -- Stdout: dnw, -- Stderr: stderrBuf, -- ExtraFiles: []*os.File{fd}, -+ Args: cmdLine, -+ Path: cmdLine[0], -+ Stdin: dnr, -+ Stdout: dnw, -+ Stderr: stderrBuf, -+ } -+ // Forward FD if one was allocated -+ if fd != nil { -+ cmd.ExtraFiles = []*os.File{fd} - } - - if err := runStartVMCommand(cmd); err != nil { -@@ -575,7 +596,7 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error { - fmt.Println("Waiting for VM ...") - } - -- conn, err = sockets.DialSocketWithBackoffsAndProcCheck(maxBackoffs, defaultBackoff, v.ReadySocket.GetPath(), checkProcessStatus, "qemu", cmd.Process.Pid, stderrBuf) -+ conn, err = sockets.DialSocketWithBackoffsAndProcCheck(maxStartupBackoffs, baseBackoff, v.ReadySocket.GetPath(), checkProcessStatus, "qemu", cmd.Process.Pid, stderrBuf) - if err != nil { - return err - } -@@ -609,7 +630,7 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error { - return nil - } - -- connected, sshError, err := v.conductVMReadinessCheck(name, maxBackoffs, defaultBackoff) -+ connected, sshError, err := v.conductVMReadinessCheck(name, maxStartupBackoffs, baseBackoff) - if err != nil { - return err - } -@@ -639,6 +660,28 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error { - return nil - } - -+func waitForVlanReady(pid int, vlanPath string) error { -+ time.Sleep(baseBackoff) -+ backoff := baseBackoff -+ for i := 0; i < maxStartupBackoffs; i++ { -+ if i > 0 { -+ time.Sleep(backoff) -+ backoff *= 2 -+ } -+ // First need to verify that gvproxy is alive, -+ // because `.sock` file could belong to a different process -+ err := checkProcessStatus(machine.ForwarderBinaryName, pid, nil) -+ if err != nil { -+ return err -+ } -+ _, err = os.Stat(vlanPath) -+ if err == nil { -+ break -+ } -+ } -+ return nil -+} -+ - func (v *MachineVM) checkStatus(monitor *qmp.SocketMonitor) (define.Status, error) { - // this is the format returned from the monitor - // {"return": {"status": "running", "singlestep": false, "running": true}} -@@ -683,7 +726,7 @@ func (v *MachineVM) checkStatus(monitor *qmp.SocketMonitor) (define.Status, erro - func (v *MachineVM) waitForMachineToStop() error { - fmt.Println("Waiting for VM to stop running...") - waitInternal := 250 * time.Millisecond -- for i := 0; i < 5; i++ { -+ for i := 0; i < retryCountForStop; i++ { - state, err := v.State(false) - if err != nil { - return err -@@ -716,15 +759,14 @@ func (v *MachineVM) ProxyPID() (int, error) { - return proxyPid, nil - } - --// cleanupVMProxyProcess kills the proxy process and removes the VM's pidfile --func (v *MachineVM) cleanupVMProxyProcess(proxyProc *os.Process) error { -+// cleanupVMProxyProcess kills the proxy process -+func (v *MachineVM) cleanupVMProxyProcess(proxyPid int) error { - // Kill the process -- if err := proxyProc.Kill(); err != nil { -+ if err := killProcess(proxyPid, false); err != nil { - return err - } -- // Remove the pidfile - if err := v.PidFilePath.Delete(); err != nil { -- return err -+ logrus.Debugf("Error while removing proxy pidfile: %v", err) - } - return nil - } -@@ -768,7 +810,7 @@ func (v *MachineVM) Stop(_ string, _ machine.StopOptions) error { - return stopErr - } - -- if err := sigKill(qemuPid); err != nil { -+ if err := killProcess(qemuPid, true); err != nil { - if stopErr == nil { - return err - } -@@ -843,7 +885,7 @@ func (v *MachineVM) stopLocked() error { - return err - } - -- if err := v.cleanupVMProxyProcess(proxyProc); err != nil { -+ if err := v.cleanupVMProxyProcess(proxyPid); err != nil { - return err - } - -@@ -875,8 +917,18 @@ func (v *MachineVM) stopLocked() error { - } - - fmt.Println("Waiting for VM to exit...") -- for isProcessAlive(vmPid) { -- time.Sleep(500 * time.Millisecond) -+ retries := 60 -+ for { -+ alive, _ := isProcessAlive(vmPid) -+ if retries <= 0 { -+ logrus.Warning("Giving up on waiting for VM to exit. VM process might still terminate") -+ break -+ } -+ if !alive { -+ break -+ } -+ time.Sleep(baseBackoff) -+ retries-- - } - - return nil -@@ -884,32 +936,42 @@ func (v *MachineVM) stopLocked() error { - - // NewQMPMonitor creates the monitor subsection of our vm - func NewQMPMonitor(network, name string, timeout time.Duration) (command.Monitor, error) { -- rtDir, err := getRuntimeDir() -+ if timeout == 0 { -+ timeout = defaultQMPTimeout -+ } -+ address, err := machineSocket(name, "qmp", "") - if err != nil { - return command.Monitor{}, err - } -+ monitor := command.Monitor{ -+ Network: network, -+ Address: *address, -+ Timeout: timeout, -+ } -+ return monitor, nil -+} -+ -+func machineSocket(name, prefix, suffix string) (*define.VMFile, error) { -+ rtDir, err := getRuntimeDir() -+ if err != nil { -+ return nil, err -+ } - if isRootful() { - rtDir = "/run" - } - rtDir = filepath.Join(rtDir, "podman") - if _, err := os.Stat(rtDir); errors.Is(err, fs.ErrNotExist) { - if err := os.MkdirAll(rtDir, 0755); err != nil { -- return command.Monitor{}, err -+ return nil, err - } - } -- if timeout == 0 { -- timeout = defaultQMPTimeout -+ if prefix != "" { -+ name = prefix + "_" + name - } -- address, err := define.NewMachineFile(filepath.Join(rtDir, "qmp_"+name+".sock"), nil) -- if err != nil { -- return command.Monitor{}, err -- } -- monitor := command.Monitor{ -- Network: network, -- Address: *address, -- Timeout: timeout, -+ if suffix != "" { -+ name = name + "_" + suffix - } -- return monitor, nil -+ return define.NewMachineFile(filepath.Join(rtDir, name+".sock"), nil) - } - - // collectFilesToDestroy retrieves the files that will be destroyed by `Remove` -@@ -1107,18 +1169,18 @@ func getDiskSize(path string) (uint64, error) { - - // startHostNetworking runs a binary on the host system that allows users - // to set up port forwarding to the podman virtual machine --func (v *MachineVM) startHostNetworking() (string, machine.APIForwardingState, error) { -+func (v *MachineVM) startHostNetworking(vlanSocket *define.VMFile) (string, machine.APIForwardingState, *os.Process, error) { - cfg, err := config.Default() - if err != nil { -- return "", machine.NoForwarding, err -+ return "", machine.NoForwarding, nil, err - } - binary, err := cfg.FindHelperBinary(machine.ForwarderBinaryName, false) - if err != nil { -- return "", machine.NoForwarding, err -+ return "", machine.NoForwarding, nil, err - } - - cmd := gvproxy.NewGvproxyCommand() -- cmd.AddQemuSocket(fmt.Sprintf("unix://%s", v.QMPMonitor.Address.GetPath())) -+ cmd.AddQemuSocket(fmt.Sprintf("unix://%s", filepath.ToSlash(vlanSocket.GetPath()))) - cmd.PidFile = v.PidFilePath.GetPath() - cmd.SSHPort = v.Port - -@@ -1133,11 +1195,13 @@ func (v *MachineVM) startHostNetworking() (string, machine.APIForwardingState, e - logrus.Debug(cmd) - } - -+ cargs := cmd.ToCmdline() -+ logrus.Debugf("gvproxy cmd: %v", append([]string{binary}, cargs...)) - c := cmd.Cmd(binary) - if err := c.Start(); err != nil { -- return "", 0, fmt.Errorf("unable to execute: %q: %w", cmd.ToCmdline(), err) -+ return "", 0, nil, fmt.Errorf("unable to execute: %q: %w", cmd.ToCmdline(), err) - } -- return forwardSock, state, nil -+ return forwardSock, state, c.Process, nil - } - - func (v *MachineVM) setupAPIForwarding(cmd gvproxy.GvproxyCommand) (gvproxy.GvproxyCommand, string, machine.APIForwardingState) { -@@ -1155,10 +1219,10 @@ func (v *MachineVM) setupAPIForwarding(cmd gvproxy.GvproxyCommand) (gvproxy.Gvpr - forwardUser = "root" - } - -- cmd.AddForwardSock(socket.GetPath()) -- cmd.AddForwardDest(destSock) -- cmd.AddForwardUser(forwardUser) -- cmd.AddForwardIdentity(v.IdentityPath) -+ err = forwardSocketArgs(&cmd, v.Name, socket.GetPath(), destSock, v.IdentityPath, forwardUser) -+ if err != nil { -+ return cmd, "", machine.NoForwarding -+ } - - // The linking pattern is /var/run/docker.sock -> user global sock (link) -> machine sock (socket) - // This allows the helper to only have to maintain one constant target to the user, which can be -@@ -1331,6 +1395,7 @@ func (v *MachineVM) Inspect() (*machine.InspectInfo, error) { - return nil, err - } - connInfo.PodmanSocket = podmanSocket -+ connInfo.PodmanPipe = podmanPipe(v.Name) - return &machine.InspectInfo{ - ConfigPath: v.ConfigPath, - ConnectionInfo: *connInfo, -@@ -1397,6 +1462,18 @@ func (v *MachineVM) editCmdLine(flag string, value string) { - } - } - -+func forwardSocketArgs(cmd *gvproxy.GvproxyCommand, name string, path string, destPath string, identityPath string, user string) error { -+ err := forwardPipeArgs(cmd, name, destPath, identityPath, user) -+ if err != nil { -+ return err -+ } -+ cmd.AddForwardSock(path) -+ cmd.AddForwardDest(destPath) -+ cmd.AddForwardUser(user) -+ cmd.AddForwardIdentity(identityPath) -+ return nil -+} -+ - func isRootful() bool { - // Rootless is not relevant on Windows. In the future rootless.IsRootless - // could be switched to return true on Windows, and other codepaths migrated -diff --git a/pkg/machine/qemu/machine_unix.go b/pkg/machine/qemu/machine_unix.go -index 37ed1f619..a684e8a31 100644 ---- a/pkg/machine/qemu/machine_unix.go -+++ b/pkg/machine/qemu/machine_unix.go -@@ -8,22 +8,43 @@ import ( - "strings" - "syscall" - -+ gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types" -+ "github.com/containers/podman/v4/pkg/machine/define" - "golang.org/x/sys/unix" - ) - --func isProcessAlive(pid int) bool { -+func isProcessAlive(pid int) (bool, error) { - err := unix.Kill(pid, syscall.Signal(0)) - if err == nil || err == unix.EPERM { -- return true -+ return true, nil -+ } -+ return false, err -+} -+ -+func pingProcess(pid int) (int, error) { -+ alive, err := isProcessAlive(pid) -+ if !alive { -+ if err == unix.ESRCH { -+ return -1, nil -+ } -+ return -1, fmt.Errorf("pinging QEMU process: %w", err) -+ } -+ return pid, nil -+} -+ -+func killProcess(pid int, force bool) error { -+ if force { -+ return unix.Kill(pid, unix.SIGKILL) -+ } else { -+ return unix.Kill(pid, unix.SIGTERM) - } -- return false - } - - func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) error { - var status syscall.WaitStatus - pid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, nil) - if err != nil { -- return fmt.Errorf("failed to read qem%su process status: %w", processHint, err) -+ return fmt.Errorf("failed to read %s process status: %w", processHint, err) - } - if pid > 0 { - // child exited -@@ -32,6 +53,14 @@ func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) er - return nil - } - -+func forwardPipeArgs(cmd *gvproxy.GvproxyCommand, name string, destPath string, identityPath string, user string) error { -+ return nil -+} -+ -+func podmanPipe(name string) *define.VMFile { -+ return nil -+} -+ - func pathsFromVolume(volume string) []string { - return strings.SplitN(volume, ":", 3) - } -@@ -42,17 +71,3 @@ func extractTargetPath(paths []string) string { - } - return paths[0] - } -- --func sigKill(pid int) error { -- return unix.Kill(pid, unix.SIGKILL) --} -- --func findProcess(pid int) (int, error) { -- if err := unix.Kill(pid, 0); err != nil { -- if err == unix.ESRCH { -- return -1, nil -- } -- return -1, fmt.Errorf("pinging QEMU process: %w", err) -- } -- return pid, nil --} -diff --git a/pkg/machine/qemu/machine_windows.go b/pkg/machine/qemu/machine_windows.go -index b31a4f1d1..2af13cb81 100644 ---- a/pkg/machine/qemu/machine_windows.go -+++ b/pkg/machine/qemu/machine_windows.go -@@ -6,14 +6,29 @@ import ( - "regexp" - "strings" - -+ gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types" - "github.com/containers/podman/v4/pkg/machine" -+ "github.com/containers/podman/v4/pkg/machine/define" - ) - --func isProcessAlive(pid int) bool { -+func isProcessAlive(pid int) (bool, error) { - if checkProcessStatus("process", pid, nil) == nil { -- return true -+ return true, nil - } -- return false -+ return false, nil -+} -+ -+func pingProcess(pid int) (int, error) { -+ alive, _ := isProcessAlive(pid) -+ if !alive { -+ return -1, nil -+ } -+ return pid, nil -+} -+ -+func killProcess(pid int, force bool) error { -+ machine.SendQuit(uint32(pid)) -+ return nil - } - - func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) error { -@@ -28,6 +43,32 @@ func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) er - return nil - } - -+func forwardPipeArgs(cmd *gvproxy.GvproxyCommand, name string, destPath string, identityPath string, user string) error { -+ machinePipe := toPipeName(name) -+ if !machine.PipeNameAvailable(machinePipe) { -+ return fmt.Errorf("could not start api proxy since expected pipe is not available: %s", machinePipe) -+ } -+ cmd.AddForwardSock(fmt.Sprintf("npipe:////./pipe/%s", machinePipe)) -+ cmd.AddForwardDest(destPath) -+ cmd.AddForwardUser(user) -+ cmd.AddForwardIdentity(identityPath) -+ return nil -+} -+ -+func podmanPipe(name string) *define.VMFile { -+ return &define.VMFile{Path: `\\.\pipe\` + toPipeName(name)} -+} -+ -+func toPipeName(name string) string { -+ if !strings.HasPrefix(name, "qemu-podman") { -+ if !strings.HasPrefix(name, "podman") { -+ name = "podman-" + name -+ } -+ name = "qemu-" + name -+ } -+ return name -+} -+ - func pathsFromVolume(volume string) []string { - paths := strings.SplitN(volume, ":", 3) - driveLetterMatcher := regexp.MustCompile(`^(?:\\\\[.?]\\)?[a-zA-Z]$`) -@@ -50,11 +91,3 @@ func extractTargetPath(paths []string) string { - dedup := regexp.MustCompile(`//+`) - return dedup.ReplaceAllLiteralString("/"+target, "/") - } -- --func sigKill(pid int) error { -- return nil --} -- --func findProcess(pid int) (int, error) { -- return -1, nil --} -diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go -index ee0301070..235412f4b 100644 ---- a/pkg/machine/wsl/machine.go -+++ b/pkg/machine/wsl/machine.go -@@ -1537,7 +1537,7 @@ func stopWinProxy(v *MachineVM) error { - if err != nil { - return nil - } -- sendQuit(tid) -+ machine.SendQuit(tid) - _ = waitTimeout(proc, 20*time.Second) - _ = os.Remove(tidFile) - -diff --git a/pkg/machine/wsl/util_windows.go b/pkg/machine/wsl/util_windows.go -index 75a943cff..3046dca85 100644 ---- a/pkg/machine/wsl/util_windows.go -+++ b/pkg/machine/wsl/util_windows.go -@@ -67,7 +67,6 @@ const ( - TOKEN_QUERY = 0x0008 - SE_PRIVILEGE_ENABLED = 0x00000002 - SE_ERR_ACCESSDENIED = 0x05 -- WM_QUIT = 0x12 - ) - - func winVersionAtLeast(major uint, minor uint, build uint) bool { -@@ -337,9 +336,3 @@ func buildCommandArgs(elevate bool) string { - } - return strings.Join(args, " ") - } -- --func sendQuit(tid uint32) { -- user32 := syscall.NewLazyDLL("user32.dll") -- postMessage := user32.NewProc("PostThreadMessageW") -- postMessage.Call(uintptr(tid), WM_QUIT, 0, 0) --} --- -2.43.0 - diff --git a/patches/podman/0002-Enable-QEMU-Podman-machine-on-Windows.patch b/patches/podman/0002-Implement-QEMU-Podman-machine-on-Windows.patch similarity index 58% rename from patches/podman/0002-Enable-QEMU-Podman-machine-on-Windows.patch rename to patches/podman/0002-Implement-QEMU-Podman-machine-on-Windows.patch index 61ae770..91021ed 100644 --- a/patches/podman/0002-Enable-QEMU-Podman-machine-on-Windows.patch +++ b/patches/podman/0002-Implement-QEMU-Podman-machine-on-Windows.patch @@ -1,22 +1,22 @@ -From eccb0da8c515ce6ba9678633d93ae521f8782bd4 Mon Sep 17 00:00:00 2001 +From 9bfba97e98cf7aa2305ff97d7e4c3276ae2d9bb3 Mon Sep 17 00:00:00 2001 From: Arthur Sengileyev -Date: Sat, 1 Apr 2023 23:49:13 +0300 -Subject: [PATCH] Enable QEMU Podman machine on Windows +Date: Tue, 20 Feb 2024 21:52:34 +0200 +Subject: [PATCH 2/2] Implement QEMU Podman machine on Windows Signed-off-by: Arthur Sengileyev --- pkg/machine/e2e/README.md | 11 +++++++++++ - pkg/machine/e2e/config_windows_test.go | 2 +- pkg/machine/e2e/init_test.go | 3 +++ pkg/machine/provider/platform_windows.go | 2 ++ pkg/machine/provider/platform_windows_amd64.go | 10 ++++++++++ pkg/machine/provider/platform_windows_arm64.go | 12 ++++++++++++ - 6 files changed, 39 insertions(+), 1 deletion(-) + pkg/machine/vmconfigs/config_windows.go | 10 +++++++++- + 6 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 pkg/machine/provider/platform_windows_amd64.go create mode 100644 pkg/machine/provider/platform_windows_arm64.go diff --git a/pkg/machine/e2e/README.md b/pkg/machine/e2e/README.md -index 5a1e324a2..30f62f5b2 100644 +index 4b737b686..2f47d739a 100644 --- a/pkg/machine/e2e/README.md +++ b/pkg/machine/e2e/README.md @@ -28,6 +28,17 @@ Note: To run specific test files, add the test files to the end of the winmake c @@ -25,7 +25,7 @@ index 5a1e324a2..30f62f5b2 100644 +### QEMU +1. Install QEMU and add it to either user or sysmem PATH variable -+1. Install Podman release (needed to have gvproxy binary) ++1. Install Podman release (is needed to have gvproxy binary) +1. Open a powershell as a regular user +1. $env:CONTAINERS_MACHINE_PROVIDER="qemu" +1. `./winmake localmachine` @@ -37,24 +37,11 @@ index 5a1e324a2..30f62f5b2 100644 ## MacOS ### Apple Hypervisor -diff --git a/pkg/machine/e2e/config_windows_test.go b/pkg/machine/e2e/config_windows_test.go -index d82a7f022..ce0c3187c 100644 ---- a/pkg/machine/e2e/config_windows_test.go -+++ b/pkg/machine/e2e/config_windows_test.go -@@ -14,7 +14,7 @@ import ( - const podmanBinary = "../../../bin/windows/podman.exe" - - func getDownloadLocation(p machine.VirtProvider) string { -- if p.VMType() == define.HyperVVirt { -+ if p.VMType() == define.HyperVVirt || p.VMType() == define.QemuVirt { - return getFCOSDownloadLocation(p) - } - fd, err := wsl.NewFedoraDownloader(define.WSLVirt, "", defaultStream.String()) diff --git a/pkg/machine/e2e/init_test.go b/pkg/machine/e2e/init_test.go -index 27b0b3d06..f1750536c 100644 +index 83f0b5c9a..cbe774b25 100644 --- a/pkg/machine/e2e/init_test.go +++ b/pkg/machine/e2e/init_test.go -@@ -189,6 +189,9 @@ var _ = Describe("podman machine init", func() { +@@ -202,6 +202,9 @@ var _ = Describe("podman machine init", func() { Skip("volumes are not supported on hyperv yet") } skipIfWSL("WSL volumes are much different. This test will not pass as is") @@ -65,13 +52,13 @@ index 27b0b3d06..f1750536c 100644 tmpDir, err := os.MkdirTemp("", "") Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/machine/provider/platform_windows.go b/pkg/machine/provider/platform_windows.go -index a57f283e3..0a4e8773a 100644 +index 943a66926..3a19f3964 100644 --- a/pkg/machine/provider/platform_windows.go +++ b/pkg/machine/provider/platform_windows.go -@@ -32,6 +32,8 @@ func Get() (machine.VirtProvider, error) { - return wsl.VirtualizationProvider(), nil +@@ -33,6 +33,8 @@ func Get() (vmconfigs.VMProvider, error) { + return new(wsl.WSLStubber), nil case define.HyperVVirt: - return hyperv.VirtualizationProvider(), nil + return new(hyperv.HyperVStubber), nil + case define.QemuVirt: + return getQemuProvider() default: @@ -79,23 +66,23 @@ index a57f283e3..0a4e8773a 100644 } diff --git a/pkg/machine/provider/platform_windows_amd64.go b/pkg/machine/provider/platform_windows_amd64.go new file mode 100644 -index 000000000..113ab2442 +index 000000000..04bfc0734 --- /dev/null +++ b/pkg/machine/provider/platform_windows_amd64.go @@ -0,0 +1,10 @@ +package provider + +import ( -+ "github.com/containers/podman/v4/pkg/machine" -+ "github.com/containers/podman/v4/pkg/machine/qemu" ++ "github.com/containers/podman/v5/pkg/machine/qemu" ++ "github.com/containers/podman/v5/pkg/machine/vmconfigs" +) + -+func getQemuProvider() (machine.VirtProvider, error) { -+ return qemu.VirtualizationProvider(), nil ++func getQemuProvider() (vmconfigs.VMProvider, error) { ++ return new(qemu.QEMUStubber), nil +} diff --git a/pkg/machine/provider/platform_windows_arm64.go b/pkg/machine/provider/platform_windows_arm64.go new file mode 100644 -index 000000000..8ec95785d +index 000000000..ded7ad7b1 --- /dev/null +++ b/pkg/machine/provider/platform_windows_arm64.go @@ -0,0 +1,12 @@ @@ -104,13 +91,43 @@ index 000000000..8ec95785d +import ( + "fmt" + -+ "github.com/containers/podman/v4/pkg/machine" -+ "github.com/containers/podman/v4/pkg/machine/define" ++ "github.com/containers/podman/v5/pkg/machine/define" ++ "github.com/containers/podman/v5/pkg/machine/vmconfigs" +) + -+func getQemuProvider() (machine.VirtProvider, error) { ++func getQemuProvider() (vmconfigs.VMProvider, error) { + return nil, fmt.Errorf("unsupported virtualization provider: `%s`", define.QemuVirt.String()) +} +diff --git a/pkg/machine/vmconfigs/config_windows.go b/pkg/machine/vmconfigs/config_windows.go +index 0562490c7..f732226f6 100644 +--- a/pkg/machine/vmconfigs/config_windows.go ++++ b/pkg/machine/vmconfigs/config_windows.go +@@ -1,7 +1,9 @@ + package vmconfigs + + import ( ++ "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/hyperv/vsock" ++ "github.com/containers/podman/v5/pkg/machine/qemu/command" + ) + + type HyperVConfig struct { +@@ -17,8 +19,14 @@ type WSLConfig struct { + UserModeNetworking bool + } + ++type QEMUConfig struct { ++ // QMPMonitor is the qemu monitor object for sending commands ++ QMPMonitor command.Monitor ++ // QEMUPidPath is where to write the PID for QEMU when running ++ QEMUPidPath *define.VMFile ++} ++ + // Stubs +-type QEMUConfig struct{} + type AppleHVConfig struct{} + + func getHostUID() int { -- -2.43.0 +2.43.2