From bb35cbe033007e9748c5f0db6a7ee90cd871169c Mon Sep 17 00:00:00 2001
From: Tomasz Maczukin <tomasz@maczukin.pl>
Date: Wed, 13 Jul 2016 04:13:45 +0200
Subject: [PATCH] Store last known status of machine in file in machine's
 storage path

Signed-off-by: Tomasz Maczukin <tomasz@maczukin.pl>
---
 .gitlab-ci.yml                  |  8 ++++++++
 libmachine/host/host.go         | 17 ++++++++++++++++-
 libmachine/libmachine.go        |  5 +++++
 libmachine/persist/filestore.go |  2 ++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e5778514..4746c6f5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,6 +7,14 @@ before_script:
 - apt-get update -yqqq
 - apt-get install -yqqq make
 
+test:
+  stage: test
+  script:
+  - make fmt lint vet test-long
+  tags:
+  - docker
+  - privileged
+
 build:
   stage: build
   script:
diff --git a/libmachine/host/host.go b/libmachine/host/host.go
index c4380050..ca768022 100644
--- a/libmachine/host/host.go
+++ b/libmachine/host/host.go
@@ -38,6 +38,7 @@ func SetSSHClientCreator(creator SSHClientCreator) {
 
 type Host struct {
 	ConfigVersion int
+	LastState     state.State `json:"-"`
 	Driver        drivers.Driver
 	DriverName    string
 	HostOptions   *Options
@@ -103,7 +104,12 @@ func (h *Host) runActionForState(action func() error, desiredState state.State)
 		return err
 	}
 
-	return mcnutils.WaitFor(drivers.MachineInState(h.Driver, desiredState))
+	if err := mcnutils.WaitFor(drivers.MachineInState(h.Driver, desiredState)); err != nil {
+		return err
+	}
+
+	h.LastState = desiredState
+	return nil
 }
 
 func (h *Host) WaitForDocker() error {
@@ -161,6 +167,8 @@ func (h *Host) Restart() error {
 		}
 	}
 
+	h.LastState = state.Running
+
 	return h.WaitForDocker()
 }
 
@@ -221,3 +229,10 @@ func (h *Host) Provision() error {
 
 	return provisioner.Provision(*h.HostOptions.SwarmOptions, *h.HostOptions.AuthOptions, *h.HostOptions.EngineOptions)
 }
+
+func (h *Host) UpdateLastState() {
+	lastState, err := h.Driver.GetState()
+	if err == nil {
+		h.LastState = lastState
+	}
+}
diff --git a/libmachine/libmachine.go b/libmachine/libmachine.go
index de177992..56084a42 100644
--- a/libmachine/libmachine.go
+++ b/libmachine/libmachine.go
@@ -61,6 +61,7 @@ func (api *Client) NewHost(driverName string, rawDriver []byte) (*host.Host, err
 
 	return &host.Host{
 		ConfigVersion: version.ConfigVersion,
+		LastState:     state.None,
 		Name:          driver.GetMachineName(),
 		Driver:        driver,
 		DriverName:    driver.DriverName(),
@@ -135,7 +136,10 @@ func (api *Client) Create(h *host.Host) error {
 	log.Info("Creating machine...")
 
 	if err := api.performCreate(h); err != nil {
+		h.UpdateLastState()
+
 		// Try to save machine when Create fails, it can store some critical information like DropletID
+		// (which in some/most DO failures cases is equal 0 :P)
 		api.Save(h)
 
 		return fmt.Errorf("Error creating machine: %s", err)
@@ -143,6 +147,7 @@ func (api *Client) Create(h *host.Host) error {
 
 	log.Debug("Reticulating splines...")
 
+	h.UpdateLastState()
 	return nil
 }
 
diff --git a/libmachine/persist/filestore.go b/libmachine/persist/filestore.go
index 3978a9ce..3eb5576e 100644
--- a/libmachine/persist/filestore.go
+++ b/libmachine/persist/filestore.go
@@ -72,6 +72,8 @@ func (s Filestore) Save(host *host.Host) error {
 		return err
 	}
 
+	s.saveToFile([]byte(host.LastState.String()), filepath.Join(hostPath, "last_state"))
+
 	return s.saveToFile(data, filepath.Join(hostPath, "config.json"))
 }
 
-- 
GitLab