mirror of
https://github.com/containers/podman.git
synced 2025-06-22 18:08:11 +08:00
Merge pull request #19455 from jakecorrenti/qemu-machine-funcs-to-methods
Convert new QEMU functions to methods with documentation
This commit is contained in:
@ -196,7 +196,10 @@ func migrateVM(configPath string, config []byte, vm *MachineVM) error {
|
|||||||
return os.Remove(configPath + ".orig")
|
return os.Remove(configPath + ".orig")
|
||||||
}
|
}
|
||||||
|
|
||||||
func acquireVMImage(opts machine.InitOptions, v *MachineVM) error {
|
// acquireVMImage determines if the image is already in a FCOS stream. If so,
|
||||||
|
// retrives the image path of the uncompressed file. Otherwise, the user has
|
||||||
|
// provided an alternative image, so we set the image path and download the image.
|
||||||
|
func (v *MachineVM) acquireVMImage(opts machine.InitOptions) error {
|
||||||
switch opts.ImagePath {
|
switch opts.ImagePath {
|
||||||
// TODO these need to be re-typed as FCOSStreams
|
// TODO these need to be re-typed as FCOSStreams
|
||||||
case machine.Testing.String(), machine.Next.String(), machine.Stable.String(), "":
|
case machine.Testing.String(), machine.Next.String(), machine.Stable.String(), "":
|
||||||
@ -240,7 +243,9 @@ func acquireVMImage(opts machine.InitOptions, v *MachineVM) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addMountsToVM(opts machine.InitOptions, v *MachineVM) error {
|
// addMountsToVM converts the volumes passed through the CLI into the specified
|
||||||
|
// volume driver and adds them to the machine
|
||||||
|
func (v *MachineVM) addMountsToVM(opts machine.InitOptions) error {
|
||||||
var volumeType string
|
var volumeType string
|
||||||
switch opts.VolumeDriver {
|
switch opts.VolumeDriver {
|
||||||
// "" is the default volume driver
|
// "" is the default volume driver
|
||||||
@ -270,7 +275,9 @@ func addMountsToVM(opts machine.InitOptions, v *MachineVM) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSSHConnectionsToPodmanSocket(opts machine.InitOptions, v *MachineVM) error {
|
// addSSHConnectionsToPodmanSocket adds SSH connections to the podman socket if
|
||||||
|
// no ignition path is provided
|
||||||
|
func (v *MachineVM) addSSHConnectionsToPodmanSocket(opts machine.InitOptions) error {
|
||||||
// This kind of stinks but no other way around this r/n
|
// This kind of stinks but no other way around this r/n
|
||||||
if len(opts.IgnitionPath) > 0 {
|
if len(opts.IgnitionPath) > 0 {
|
||||||
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
|
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
|
||||||
@ -297,7 +304,9 @@ func addSSHConnectionsToPodmanSocket(opts machine.InitOptions, v *MachineVM) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeIgnitionConfigFile(opts machine.InitOptions, v *MachineVM, key string) error {
|
// writeIgnitionConfigFile generates the ignition config and writes it to the
|
||||||
|
// filesystem
|
||||||
|
func (v *MachineVM) writeIgnitionConfigFile(opts machine.InitOptions, key string) error {
|
||||||
ign := &machine.DynamicIgnition{
|
ign := &machine.DynamicIgnition{
|
||||||
Name: opts.Username,
|
Name: opts.Username,
|
||||||
Key: key,
|
Key: key,
|
||||||
@ -348,14 +357,14 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
v.IdentityPath = util.GetIdentityPath(v.Name)
|
v.IdentityPath = util.GetIdentityPath(v.Name)
|
||||||
v.Rootful = opts.Rootful
|
v.Rootful = opts.Rootful
|
||||||
|
|
||||||
if err := acquireVMImage(opts, v); err != nil {
|
if err := v.acquireVMImage(opts); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add arch specific options including image location
|
// Add arch specific options including image location
|
||||||
v.CmdLine = append(v.CmdLine, v.addArchOptions()...)
|
v.CmdLine = append(v.CmdLine, v.addArchOptions()...)
|
||||||
|
|
||||||
if err := addMountsToVM(opts, v); err != nil {
|
if err := v.addMountsToVM(opts); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +373,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
// Add location of bootable image
|
// Add location of bootable image
|
||||||
v.CmdLine = append(v.CmdLine, "-drive", "if=virtio,file="+v.getImageFile())
|
v.CmdLine = append(v.CmdLine, "-drive", "if=virtio,file="+v.getImageFile())
|
||||||
|
|
||||||
if err := addSSHConnectionsToPodmanSocket(opts, v); err != nil {
|
if err := v.addSSHConnectionsToPodmanSocket(opts); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +418,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
return false, os.WriteFile(v.getIgnitionFile(), inputIgnition, 0644)
|
return false, os.WriteFile(v.getIgnitionFile(), inputIgnition, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = writeIgnitionConfigFile(opts, v, key)
|
err = v.writeIgnitionConfigFile(opts, key)
|
||||||
return err == nil, err
|
return err == nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,7 +484,9 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) {
|
|||||||
return setErrors, nil
|
return setErrors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func mountVolumesToVM(v *MachineVM, opts machine.StartOptions, name string) error {
|
// mountVolumesToVM iterates through the machine's volumes and mounts them to the
|
||||||
|
// machine
|
||||||
|
func (v *MachineVM) mountVolumesToVM(opts machine.StartOptions, name string) error {
|
||||||
for _, mount := range v.Mounts {
|
for _, mount := range v.Mounts {
|
||||||
if !opts.Quiet {
|
if !opts.Quiet {
|
||||||
fmt.Printf("Mounting volume... %s:%s\n", mount.Source, mount.Target)
|
fmt.Printf("Mounting volume... %s:%s\n", mount.Source, mount.Target)
|
||||||
@ -514,7 +525,9 @@ func mountVolumesToVM(v *MachineVM, opts machine.StartOptions, name string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func conductVMReadinessCheck(v *MachineVM, name string, maxBackoffs int, backoff time.Duration) (connected bool, sshError error, err error) {
|
// conductVMReadinessCheck checks to make sure the machine is in the proper state
|
||||||
|
// and that SSH is up and running
|
||||||
|
func (v *MachineVM) conductVMReadinessCheck(name string, maxBackoffs int, backoff time.Duration) (connected bool, sshError error, err error) {
|
||||||
for i := 0; i < maxBackoffs; i++ {
|
for i := 0; i < maxBackoffs; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
time.Sleep(backoff)
|
time.Sleep(backoff)
|
||||||
@ -543,6 +556,7 @@ func conductVMReadinessCheck(v *MachineVM, name string, maxBackoffs int, backoff
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runStartVMCommand executes the command to start the VM
|
||||||
func runStartVMCommand(cmd *exec.Cmd) error {
|
func runStartVMCommand(cmd *exec.Cmd) error {
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -569,13 +583,15 @@ func runStartVMCommand(cmd *exec.Cmd) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectToQMPMonitorSocket(maxBackoffs int, backoff time.Duration, path string) (conn net.Conn, err error) {
|
// connectToQMPMonitorSocket attempts to connect to the QMP Monitor Socket after
|
||||||
|
// `maxBackoffs` attempts
|
||||||
|
func (v *MachineVM) connectToQMPMonitorSocket(maxBackoffs int, backoff time.Duration) (conn net.Conn, err error) {
|
||||||
for i := 0; i < maxBackoffs; i++ {
|
for i := 0; i < maxBackoffs; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
time.Sleep(backoff)
|
time.Sleep(backoff)
|
||||||
backoff *= 2
|
backoff *= 2
|
||||||
}
|
}
|
||||||
conn, err = net.Dial("unix", path)
|
conn, err = net.Dial("unix", v.QMPMonitor.Address.Path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -583,7 +599,9 @@ func connectToQMPMonitorSocket(maxBackoffs int, backoff time.Duration, path stri
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectToPodmanSocket(maxBackoffs int, backoff time.Duration, qemuPID int, errBuf *bytes.Buffer, vmName string) (conn net.Conn, dialErr error) {
|
// connectToPodmanSocket attempts to connect to the podman socket after
|
||||||
|
// `maxBackoffs` attempts.
|
||||||
|
func (v *MachineVM) connectToPodmanSocket(maxBackoffs int, backoff time.Duration, qemuPID int, errBuf *bytes.Buffer) (conn net.Conn, dialErr error) {
|
||||||
socketPath, err := getRuntimeDir()
|
socketPath, err := getRuntimeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -597,7 +615,7 @@ func connectToPodmanSocket(maxBackoffs int, backoff time.Duration, qemuPID int,
|
|||||||
time.Sleep(backoff)
|
time.Sleep(backoff)
|
||||||
backoff *= 2
|
backoff *= 2
|
||||||
}
|
}
|
||||||
conn, dialErr = net.Dial("unix", filepath.Join(socketPath, "podman", vmName+"_ready.sock"))
|
conn, dialErr = net.Dial("unix", filepath.Join(socketPath, "podman", v.Name+"_ready.sock"))
|
||||||
if dialErr == nil {
|
if dialErr == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -611,6 +629,7 @@ func connectToPodmanSocket(maxBackoffs int, backoff time.Duration, qemuPID int,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getDevNullFiles returns pointers to Read-only and Write-only DevNull files
|
||||||
func getDevNullFiles() (*os.File, *os.File, error) {
|
func getDevNullFiles() (*os.File, *os.File, error) {
|
||||||
dnr, err := os.OpenFile(os.DevNull, os.O_RDONLY, 0755)
|
dnr, err := os.OpenFile(os.DevNull, os.O_RDONLY, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -708,7 +727,7 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
qemuSocketConn, err = connectToQMPMonitorSocket(maxBackoffs, defaultBackoff, v.QMPMonitor.Address.GetPath())
|
qemuSocketConn, err = v.connectToQMPMonitorSocket(maxBackoffs, defaultBackoff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -763,7 +782,7 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error {
|
|||||||
fmt.Println("Waiting for VM ...")
|
fmt.Println("Waiting for VM ...")
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err = connectToPodmanSocket(maxBackoffs, defaultBackoff, cmd.Process.Pid, stderrBuf, v.Name)
|
conn, err = v.connectToPodmanSocket(maxBackoffs, defaultBackoff, cmd.Process.Pid, stderrBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -789,7 +808,7 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
connected, sshError, err := conductVMReadinessCheck(v, name, maxBackoffs, defaultBackoff)
|
connected, sshError, err := v.conductVMReadinessCheck(name, maxBackoffs, defaultBackoff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -803,7 +822,7 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// mount the volumes to the VM
|
// mount the volumes to the VM
|
||||||
if err := mountVolumesToVM(v, opts, name); err != nil {
|
if err := v.mountVolumesToVM(opts, name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,7 +899,8 @@ func (v *MachineVM) checkStatus(monitor *qmp.SocketMonitor) (machine.Status, err
|
|||||||
return machine.Stopped, nil
|
return machine.Stopped, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForMachine(v *MachineVM) error {
|
// waitForMachineToStop waits for the machine to stop running
|
||||||
|
func (v *MachineVM) waitForMachineToStop() error {
|
||||||
fmt.Println("Waiting for VM to stop running...")
|
fmt.Println("Waiting for VM to stop running...")
|
||||||
waitInternal := 250 * time.Millisecond
|
waitInternal := 250 * time.Millisecond
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
@ -900,11 +920,12 @@ func waitForMachine(v *MachineVM) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getProxyPID(pidFilePath machine.VMFile) (int, error) {
|
// ProxyPID retrieves the pid from the proxy pidfile
|
||||||
if _, err := os.Stat(pidFilePath.GetPath()); errors.Is(err, fs.ErrNotExist) {
|
func (v *MachineVM) ProxyPID() (int, error) {
|
||||||
|
if _, err := os.Stat(v.PidFilePath.Path); errors.Is(err, fs.ErrNotExist) {
|
||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
proxyPidString, err := pidFilePath.Read()
|
proxyPidString, err := v.PidFilePath.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
@ -915,20 +936,22 @@ func getProxyPID(pidFilePath machine.VMFile) (int, error) {
|
|||||||
return proxyPid, nil
|
return proxyPid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanupVMProxyProcess(pidFile machine.VMFile, proxyProc *os.Process) error {
|
// cleanupVMProxyProcess kills the proxy process and removes the VM's pidfile
|
||||||
|
func (v *MachineVM) cleanupVMProxyProcess(proxyProc *os.Process) error {
|
||||||
// Kill the process
|
// Kill the process
|
||||||
if err := proxyProc.Kill(); err != nil {
|
if err := proxyProc.Kill(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Remove the pidfile
|
// Remove the pidfile
|
||||||
if err := pidFile.Delete(); err != nil {
|
if err := v.PidFilePath.Delete(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVMPid(vmPidFile machine.VMFile) (int, error) {
|
// VMPid retrieves the pid from the VM's pidfile
|
||||||
vmPidString, err := vmPidFile.Read()
|
func (v *MachineVM) VMPid() (int, error) {
|
||||||
|
vmPidString, err := v.VMPidFilePath.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
@ -1003,7 +1026,7 @@ func (v *MachineVM) stopLocked() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyPid, err := getProxyPID(v.PidFilePath)
|
proxyPid, err := v.ProxyPID()
|
||||||
if err != nil || proxyPid < 0 {
|
if err != nil || proxyPid < 0 {
|
||||||
// may return nil if proxyPid == -1 because the pidfile does not exist
|
// may return nil if proxyPid == -1 because the pidfile does not exist
|
||||||
return err
|
return err
|
||||||
@ -1019,7 +1042,7 @@ func (v *MachineVM) stopLocked() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cleanupVMProxyProcess(v.PidFilePath, proxyProc); err != nil {
|
if err := v.cleanupVMProxyProcess(proxyProc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,10 +1065,10 @@ func (v *MachineVM) stopLocked() error {
|
|||||||
// no vm pid file path means it's probably a machine created before we
|
// no vm pid file path means it's probably a machine created before we
|
||||||
// started using it, so we revert to the old way of waiting for the
|
// started using it, so we revert to the old way of waiting for the
|
||||||
// machine to stop
|
// machine to stop
|
||||||
return waitForMachine(v)
|
return v.waitForMachineToStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
vmPid, err := getVMPid(v.VMPidFilePath)
|
vmPid, err := v.VMPid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1088,7 +1111,8 @@ func NewQMPMonitor(network, name string, timeout time.Duration) (Monitor, error)
|
|||||||
return monitor, nil
|
return monitor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectFilesToDestroy(v *MachineVM, opts machine.RemoveOptions) ([]string, error) {
|
// collectFilesToDestroy retrieves the files that will be destroyed by `Remove`
|
||||||
|
func (v *MachineVM) collectFilesToDestroy(opts machine.RemoveOptions) ([]string, error) {
|
||||||
files := []string{}
|
files := []string{}
|
||||||
// Collect all the files that need to be destroyed
|
// Collect all the files that need to be destroyed
|
||||||
if !opts.SaveKeys {
|
if !opts.SaveKeys {
|
||||||
@ -1119,28 +1143,32 @@ func collectFilesToDestroy(v *MachineVM, opts machine.RemoveOptions) ([]string,
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeQMPMonitorSocketAndVMPidFile(vmPidFile, proxyPidFile machine.VMFile, qmpMonitor machine.VMFile) {
|
// removeQMPMonitorSocketAndVMPidFile removes the VM pidfile, proxy pidfile,
|
||||||
|
// and QMP Monitor Socket
|
||||||
|
func (v *MachineVM) removeQMPMonitorSocketAndVMPidFile() {
|
||||||
// remove socket and pid file if any: warn at low priority if things fail
|
// remove socket and pid file if any: warn at low priority if things fail
|
||||||
// Remove the pidfile
|
// Remove the pidfile
|
||||||
if err := vmPidFile.Delete(); err != nil {
|
if err := v.VMPidFilePath.Delete(); err != nil {
|
||||||
logrus.Debugf("Error while removing VM pidfile: %v", err)
|
logrus.Debugf("Error while removing VM pidfile: %v", err)
|
||||||
}
|
}
|
||||||
if err := proxyPidFile.Delete(); err != nil {
|
if err := v.PidFilePath.Delete(); err != nil {
|
||||||
logrus.Debugf("Error while removing proxy pidfile: %v", err)
|
logrus.Debugf("Error while removing proxy pidfile: %v", err)
|
||||||
}
|
}
|
||||||
// Remove socket
|
// Remove socket
|
||||||
if err := qmpMonitor.Delete(); err != nil {
|
if err := v.QMPMonitor.Address.Delete(); err != nil {
|
||||||
logrus.Debugf("Error while removing podman-machine-socket: %v", err)
|
logrus.Debugf("Error while removing podman-machine-socket: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeFilesAndConnections(files []string, name string) {
|
// removeFilesAndConnections removes any files and connections associated with
|
||||||
|
// the machine during `Remove`
|
||||||
|
func (v *MachineVM) removeFilesAndConnections(files []string) {
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if err := os.Remove(f); err != nil && !errors.Is(err, os.ErrNotExist) {
|
if err := os.Remove(f); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := machine.RemoveConnections(name, name+"-root"); err != nil {
|
if err := machine.RemoveConnections(v.Name, v.Name+"-root"); err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1172,7 +1200,7 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err = collectFilesToDestroy(v, opts)
|
files, err = v.collectFilesToDestroy(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
@ -1182,11 +1210,11 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func()
|
|||||||
confirmationMessage += msg + "\n"
|
confirmationMessage += msg + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
removeQMPMonitorSocketAndVMPidFile(v.VMPidFilePath, v.PidFilePath, v.QMPMonitor.Address)
|
v.removeQMPMonitorSocketAndVMPidFile()
|
||||||
|
|
||||||
confirmationMessage += "\n"
|
confirmationMessage += "\n"
|
||||||
return confirmationMessage, func() error {
|
return confirmationMessage, func() error {
|
||||||
removeFilesAndConnections(files, v.Name)
|
v.removeFilesAndConnections(files)
|
||||||
return nil
|
return nil
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user