summaryrefslogtreecommitdiff
path: root/pkg/machine/qemu/machine.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/machine/qemu/machine.go')
-rw-r--r--pkg/machine/qemu/machine.go81
1 files changed, 55 insertions, 26 deletions
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index d30e51215..ac8e7d75c 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -34,7 +34,7 @@ import (
var (
qemuProvider = &Provider{}
- // vmtype refers to qemu (vs libvirt, krun, etc)
+ // vmtype refers to qemu (vs libvirt, krun, etc).
vmtype = "qemu"
)
@@ -98,7 +98,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
return nil, err
}
- cmd := append([]string{execPath})
+ cmd := []string{execPath}
// Add memory
cmd = append(cmd, []string{"-m", strconv.Itoa(int(vm.Memory))}...)
// Add cpus
@@ -111,7 +111,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
return nil, err
}
vm.QMPMonitor = monitor
- cmd = append(cmd, []string{"-qmp", monitor.Network + ":/" + monitor.Address + ",server=on,wait=off"}...)
+ cmd = append(cmd, []string{"-qmp", monitor.Network + ":/" + monitor.Address.GetPath() + ",server=on,wait=off"}...)
// Add network
// Right now the mac address is hardcoded so that the host networking gives it a specific IP address. This is
@@ -134,7 +134,8 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
// LoadByName reads a json file that describes a known qemu vm
// and returns a vm instance
func (p *Provider) LoadVMByName(name string) (machine.VM, error) {
- vm := &MachineVM{UID: -1} // posix reserves -1, so use it to signify undefined
+ vm := &MachineVM{Name: name}
+ vm.HostUser = HostUser{UID: -1} // posix reserves -1, so use it to signify undefined
vmConfigDir, err := machine.GetConfDir(vmtype)
if err != nil {
return nil, err
@@ -176,7 +177,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
v.Rootful = opts.Rootful
switch opts.ImagePath {
- case "testing", "next", "stable", "":
+ case Testing, Next, Stable, "":
// Get image as usual
v.ImageStream = opts.ImagePath
dd, err := machine.NewFcosDownloader(vmtype, v.Name, opts.ImagePath)
@@ -278,7 +279,9 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
}
// Write the JSON file
- v.writeConfig()
+ if err := v.writeConfig(); err != nil {
+ return false, fmt.Errorf("writing JSON file: %w", err)
+ }
// User has provided ignition file so keygen
// will be skipped.
@@ -315,7 +318,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
resize.Stdout = os.Stdout
resize.Stderr = os.Stderr
if err := resize.Run(); err != nil {
- return false, errors.Errorf("error resizing image: %q", err)
+ return false, errors.Errorf("resizing image: %q", err)
}
}
// If the user provides an ignition file, we need to
@@ -370,7 +373,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
conn net.Conn
err error
qemuSocketConn net.Conn
- wait time.Duration = time.Millisecond * 500
+ wait = time.Millisecond * 500
)
if v.isIncompatible() {
@@ -428,13 +431,29 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
// Disable graphic window when not in debug mode
// Done in start, so we're not suck with the debug level we used on init
- if logrus.GetLevel() != logrus.DebugLevel {
+ if !logrus.IsLevelEnabled(logrus.DebugLevel) {
cmd = append(cmd, "-display", "none")
}
_, err = os.StartProcess(v.CmdLine[0], cmd, attr)
if err != nil {
- return err
+ // check if qemu was not found
+ if !errors.Is(err, os.ErrNotExist) {
+ return err
+ }
+ // lookup qemu again maybe the path was changed, https://github.com/containers/podman/issues/13394
+ cfg, err := config.Default()
+ if err != nil {
+ return err
+ }
+ cmd[0], err = cfg.FindHelperBinary(QemuCommand, true)
+ if err != nil {
+ return err
+ }
+ _, err = os.StartProcess(cmd[0], cmd, attr)
+ if err != nil {
+ return err
+ }
}
fmt.Println("Waiting for VM ...")
socketPath, err := getRuntimeDir()
@@ -558,12 +577,12 @@ func (v *MachineVM) checkStatus(monitor *qmp.SocketMonitor) (machine.QemuMachine
func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
var disconnected bool
// check if the qmp socket is there. if not, qemu instance is gone
- if _, err := os.Stat(v.QMPMonitor.Address); os.IsNotExist(err) {
+ if _, err := os.Stat(v.QMPMonitor.Address.GetPath()); os.IsNotExist(err) {
// Right now it is NOT an error to stop a stopped machine
logrus.Debugf("QMP monitor socket %v does not exist", v.QMPMonitor.Address)
return nil
}
- qmpMonitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address, v.QMPMonitor.Timeout)
+ qmpMonitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address.GetPath(), v.QMPMonitor.Timeout)
if err != nil {
return err
}
@@ -626,7 +645,8 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
}
if err := qmpMonitor.Disconnect(); err != nil {
- return nil
+ // FIXME: this error should probably be returned
+ return nil // nolint: nilerr
}
disconnected = true
@@ -665,20 +685,25 @@ func NewQMPMonitor(network, name string, timeout time.Duration) (Monitor, error)
if timeout == 0 {
timeout = defaultQMPTimeout
}
+ address, err := NewMachineFile(filepath.Join(rtDir, "qmp+"+name+".sock"), nil)
+ if err != nil {
+ return Monitor{}, err
+ }
monitor := Monitor{
Network: network,
- Address: filepath.Join(rtDir, "qmp_"+name+".sock"),
+ Address: *address,
Timeout: timeout,
}
return monitor, nil
}
+// Remove deletes all the files associated with a machine including ssh keys, the image itself
func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, func() error, error) {
var (
files []string
)
- // cannot remove a running vm
+ // cannot remove a running vm unless --force is used
running, err := v.isRunning()
if err != nil {
return "", nil, err
@@ -749,13 +774,14 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun
func (v *MachineVM) isRunning() (bool, error) {
// Check if qmp socket path exists
- if _, err := os.Stat(v.QMPMonitor.Address); os.IsNotExist(err) {
+ if _, err := os.Stat(v.QMPMonitor.Address.GetPath()); os.IsNotExist(err) {
return false, nil
}
// Check if we can dial it
- monitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address, v.QMPMonitor.Timeout)
+ monitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address.GetPath(), v.QMPMonitor.Timeout)
if err != nil {
- return false, nil
+ // FIXME: this error should probably be returned
+ return false, nil // nolint: nilerr
}
if err := monitor.Connect(); err != nil {
return false, err
@@ -778,7 +804,7 @@ func (v *MachineVM) isRunning() (bool, error) {
func (v *MachineVM) isListening() bool {
// Check if we can dial it
- conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "localhost", v.Port), 10*time.Millisecond)
+ conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", v.Port), 10*time.Millisecond)
if err != nil {
return false
}
@@ -875,10 +901,10 @@ func GetVMInfos() ([]*machine.ListResponse, error) {
var listed []*machine.ListResponse
- if err = filepath.Walk(vmConfigDir, func(path string, info os.FileInfo, err error) error {
+ if err = filepath.WalkDir(vmConfigDir, func(path string, d fs.DirEntry, err error) error {
vm := new(MachineVM)
- if strings.HasSuffix(info.Name(), ".json") {
- fullPath := filepath.Join(vmConfigDir, info.Name())
+ if strings.HasSuffix(d.Name(), ".json") {
+ fullPath := filepath.Join(vmConfigDir, d.Name())
b, err := ioutil.ReadFile(fullPath)
if err != nil {
return err
@@ -1058,7 +1084,7 @@ func (v *MachineVM) isIncompatible() bool {
func (v *MachineVM) getForwardSocketPath() (string, error) {
path, err := machine.GetDataDir(v.Name)
if err != nil {
- logrus.Errorf("Error resolving data dir: %s", err.Error())
+ logrus.Errorf("Resolving data dir: %s", err.Error())
return "", nil
}
return filepath.Join(path, "podman.sock"), nil
@@ -1097,10 +1123,13 @@ func waitAndPingAPI(sock string) {
Transport: &http.Transport{
DialContext: func(context.Context, string, string) (net.Conn, error) {
con, err := net.DialTimeout("unix", sock, apiUpTimeout)
- if err == nil {
- con.SetDeadline(time.Now().Add(apiUpTimeout))
+ if err != nil {
+ return nil, err
+ }
+ if err := con.SetDeadline(time.Now().Add(apiUpTimeout)); err != nil {
+ return nil, err
}
- return con, err
+ return con, nil
},
},
}