mirror of
https://github.com/containers/podman.git
synced 2025-05-21 17:16:22 +08:00
Fix race conditions in hyperv readiness checking
- Listen before starting the vm - Fix a device race caused by lazy hv_vsock init by waiting on network manager [NO NEW TESTS NEEDED] Signed-off-by: Jason T. Greene <jason.greene@redhat.com>
This commit is contained in:
@ -215,8 +215,15 @@ func (h HyperVStubber) StartVM(mc *vmconfigs.MachineConfig) (func() error, func(
|
|||||||
callbackFuncs.Add(rmIgnCallbackFunc)
|
callbackFuncs.Add(rmIgnCallbackFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waitReady, listener, err := mc.HyperVHypervisor.ReadyVsock.ListenSetupWait()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
err = vm.Start()
|
err = vm.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// cleanup the pending listener
|
||||||
|
_ = listener.Close()
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +232,7 @@ func (h HyperVStubber) StartVM(mc *vmconfigs.MachineConfig) (func() error, func(
|
|||||||
}
|
}
|
||||||
callbackFuncs.Add(startCallback)
|
callbackFuncs.Add(startCallback)
|
||||||
|
|
||||||
return nil, mc.HyperVHypervisor.ReadyVsock.Listen, err
|
return nil, waitReady, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// State is returns the state as a define.status. for hyperv, state differs from others because
|
// State is returns the state as a define.status. for hyperv, state differs from others because
|
||||||
|
@ -5,6 +5,7 @@ package vsock
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -258,21 +259,18 @@ func (hv *HVSockRegistryEntry) Listener() (net.Listener, error) {
|
|||||||
return listener, nil
|
return listener, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen is used on the windows side to listen for anything to come
|
// ListenSetupWait creates an hvsock on the windows side and returns
|
||||||
// over the hvsock as a signal the vm is booted
|
// a wait function that, when called, blocks until it receives a ready
|
||||||
func (hv *HVSockRegistryEntry) Listen() error {
|
// notification on the vsock
|
||||||
|
func (hv *HVSockRegistryEntry) ListenSetupWait() (func() error, io.Closer, error) {
|
||||||
listener, err := hv.Listener()
|
listener, err := hv.Listener()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if err := listener.Close(); err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
go sockets.ListenAndWaitOnSocket(errChan, listener)
|
go sockets.ListenAndWaitOnSocket(errChan, listener)
|
||||||
|
return func() error {
|
||||||
return <-errChan
|
return <-errChan
|
||||||
|
}, listener, nil
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,9 @@ func CreateReadyUnitFile(provider define.VMType, opts *ReadyUnitOpts) (string, e
|
|||||||
if opts == nil || opts.Port == 0 {
|
if opts == nil || opts.Port == 0 {
|
||||||
return "", errors.New("no port provided for hyperv ready unit")
|
return "", errors.New("no port provided for hyperv ready unit")
|
||||||
}
|
}
|
||||||
|
readyUnit.Add("Unit", "Requires", "sys-devices-virtual-net-vsock0.device")
|
||||||
readyUnit.Add("Unit", "After", "systemd-user-sessions.service")
|
readyUnit.Add("Unit", "After", "systemd-user-sessions.service")
|
||||||
|
readyUnit.Add("Unit", "After", "vsock-network.service")
|
||||||
readyUnit.Add("Service", "ExecStart", fmt.Sprintf("/bin/sh -c '/usr/bin/echo Ready | socat - VSOCK-CONNECT:2:%d'", opts.Port))
|
readyUnit.Add("Service", "ExecStart", fmt.Sprintf("/bin/sh -c '/usr/bin/echo Ready | socat - VSOCK-CONNECT:2:%d'", opts.Port))
|
||||||
case define.WSLVirt: // WSL does not use ignition
|
case define.WSLVirt: // WSL does not use ignition
|
||||||
return "", nil
|
return "", nil
|
||||||
|
Reference in New Issue
Block a user