diff options
author | cdoern <cbdoer23@g.holycross.edu> | 2022-04-12 22:21:33 -0400 |
---|---|---|
committer | cdoern <cbdoer23@g.holycross.edu> | 2022-04-25 14:14:45 -0400 |
commit | d441a711e5590cc579ae0e0a73ea463718d4d79e (patch) | |
tree | 415249c671acb4223867b879749efa5221786fe9 | |
parent | ba6356280a86531d3cda7016859aef98bb3d8272 (diff) | |
download | podman-d441a711e5590cc579ae0e0a73ea463718d4d79e.tar.gz podman-d441a711e5590cc579ae0e0a73ea463718d4d79e.tar.bz2 podman-d441a711e5590cc579ae0e0a73ea463718d4d79e.zip |
machine starting status
podman machine was using the file modification time to get the running status
add three new config entries Starting (bool) Created (time) LastUp (time) to actually
keep track of when these events happened. This means we can use the config file
to actually store this data and not mess up the created/last-up time.
This fixes the issues where the machine would report running 15 seconds before it was up.
Also fixes the issue of modifying the file manually and saying the machine is "up"
[NO NEW TESTS NEEDED]
resolves #13711
Signed-off-by: cdoern <cbdoer23@g.holycross.edu>
-rw-r--r-- | capture.pcap | bin | 0 -> 200 bytes | |||
-rw-r--r-- | cmd/podman/machine/inspect.go | 2 | ||||
-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 |
6 files changed, 64 insertions, 23 deletions
diff --git a/capture.pcap b/capture.pcap Binary files differnew file mode 100644 index 000000000..89b48a507 --- /dev/null +++ b/capture.pcap diff --git a/cmd/podman/machine/inspect.go b/cmd/podman/machine/inspect.go index d43cabf6b..1884cf94d 100644 --- a/cmd/podman/machine/inspect.go +++ b/cmd/podman/machine/inspect.go @@ -59,7 +59,7 @@ func inspect(cmd *cobra.Command, args []string) error { errs = append(errs, err) continue } - state, err := vm.State() + state, err := vm.State(false) if err != nil { errs = append(errs, err) continue 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 } |