diff options
Diffstat (limited to 'pkg/machine')
-rw-r--r-- | pkg/machine/config.go | 2 | ||||
-rw-r--r-- | pkg/machine/qemu/config.go | 6 | ||||
-rw-r--r-- | pkg/machine/qemu/machine.go | 75 | ||||
-rw-r--r-- | pkg/machine/wsl/machine.go | 2 |
4 files changed, 63 insertions, 22 deletions
diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 5dc5f6105..505311264 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -121,7 +121,7 @@ type VM interface { Set(name string, opts SetOptions) error SSH(name string, opts SSHOptions) error Start(name string, opts StartOptions) error - State() (Status, error) + State(bypass bool) (Status, error) Stop(name string, opts StopOptions) error } diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index e9416dc36..840bd5c59 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -86,6 +86,12 @@ type MachineVM struct { ResourceConfig // SSHConfig for accessing the remote vm SSHConfig + // Starting tells us whether the machine is running or if we have just dialed it to start it + Starting bool + // Created contains the original created time instead of querying the file mod time + Created time.Time + // LastUp contains the last recorded uptime + LastUp time.Time } // ImageConfig describes the bootable image for the VM diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 66f5291c1..c54d18a4b 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -95,6 +95,8 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) { vm.Memory = opts.Memory vm.DiskSize = opts.DiskSize + vm.Created = time.Now() + // Find the qemu executable cfg, err := config.Default() if err != nil { @@ -439,7 +441,7 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) error { return nil } - state, err := v.State() + state, err := v.State(false) if err != nil { return err } @@ -480,6 +482,17 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { wait = time.Millisecond * 500 ) + v.Starting = true + if err := v.writeConfig(); err != nil { + return fmt.Errorf("writing JSON file: %w", err) + } + defer func() error { + v.Starting = false + if err := v.writeConfig(); err != nil { + return fmt.Errorf("writing JSON file: %w", err) + } + return nil + }() if v.isIncompatible() { logrus.Errorf("machine %q is incompatible with this release of podman and needs to be recreated, starting for recovery only", v.Name) } @@ -501,6 +514,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { return err } } + // 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 { @@ -581,14 +595,14 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { } if len(v.Mounts) > 0 { - state, err := v.State() + state, err := v.State(true) if err != nil { return err } listening := v.isListening() for state != machine.Running || !listening { time.Sleep(100 * time.Millisecond) - state, err = v.State() + state, err = v.State(true) if err != nil { return err } @@ -630,7 +644,6 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { } v.waitAPIAndPrintInfo(forwardState, forwardSock) - return nil } @@ -639,9 +652,10 @@ func (v *MachineVM) checkStatus(monitor *qmp.SocketMonitor) (machine.Status, err // {"return": {"status": "running", "singlestep": false, "running": true}} type statusDetails struct { - Status string `json:"status"` - Step bool `json:"singlestep"` - Running bool `json:"running"` + Status string `json:"status"` + Step bool `json:"singlestep"` + Running bool `json:"running"` + Starting bool `json:"starting"` } type statusResponse struct { Response statusDetails `json:"return"` @@ -727,6 +741,11 @@ func (v *MachineVM) Stop(_ string, _ machine.StopOptions) error { if p == nil && err != nil { return err } + + v.LastUp = time.Now() + if err := v.writeConfig(); err != nil { // keep track of last up + return err + } // Kill the process if err := p.Kill(); err != nil { return err @@ -748,7 +767,7 @@ func (v *MachineVM) Stop(_ string, _ machine.StopOptions) error { disconnected = true waitInternal := 250 * time.Millisecond for i := 0; i < 5; i++ { - state, err := v.State() + state, err := v.State(false) if err != nil { return err } @@ -800,7 +819,7 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func() ) // cannot remove a running vm unless --force is used - state, err := v.State() + state, err := v.State(false) if err != nil { return "", nil, err } @@ -866,12 +885,19 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func() }, nil } -func (v *MachineVM) State() (machine.Status, error) { +func (v *MachineVM) State(bypass bool) (machine.Status, error) { // Check if qmp socket path exists if _, err := os.Stat(v.QMPMonitor.Address.GetPath()); os.IsNotExist(err) { return "", nil } + err := v.update() + if err != nil { + return "", err + } // Check if we can dial it + if v.Starting && !bypass { + return "", nil + } monitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address.GetPath(), v.QMPMonitor.Timeout) if err != nil { // FIXME: this error should probably be returned @@ -902,7 +928,7 @@ func (v *MachineVM) isListening() bool { // SSH opens an interactive SSH session to the vm specified. // Added ssh function to VM interface: pkg/machine/config/go : line 58 func (v *MachineVM) SSH(_ string, opts machine.SSHOptions) error { - state, err := v.State() + state, err := v.State(true) if err != nil { return err } @@ -1016,20 +1042,29 @@ func getVMInfos() ([]*machine.ListResponse, error) { listEntry.Port = vm.Port listEntry.RemoteUsername = vm.RemoteUsername listEntry.IdentityPath = vm.IdentityPath - fi, err := os.Stat(fullPath) - if err != nil { - return err + listEntry.CreatedAt = vm.Created + + if listEntry.CreatedAt.IsZero() { + listEntry.CreatedAt = time.Now() + vm.Created = time.Now() + if err := vm.writeConfig(); err != nil { + return err + } } - listEntry.CreatedAt = fi.ModTime() - fi, err = os.Stat(vm.getImageFile()) + state, err := vm.State(false) if err != nil { return err } - listEntry.LastUp = fi.ModTime() - state, err := vm.State() - if err != nil { - return err + + if !vm.LastUp.IsZero() { + listEntry.LastUp = vm.LastUp + } else { + listEntry.LastUp = vm.Created + vm.Created = time.Now() + if err := vm.writeConfig(); err != nil { + return err + } } if state == machine.Running { listEntry.Running = true diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index dc3f33fa7..6e0453f8f 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -1024,7 +1024,7 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { // TODO: We need to rename isRunning to State(); I do not have a // windows system to test this on. -func (v *MachineVM) State() (machine.Status, error) { +func (v *MachineVM) State(bypass bool) (machine.Status, error) { return "", define.ErrNotImplemented } |