From 10ce4cbe2a2871f07992a78b77a9101fc22b03d9 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 26 Feb 2016 17:32:39 -0600 Subject: [PATCH] Got full spin up and spin down procedure working. --- dospin.go | 5 +++ dropletmanager.go | 80 ++++++++++++++++++++++++++++++++++++++++++++--- list_droplets.sh | 2 ++ 3 files changed, 82 insertions(+), 5 deletions(-) create mode 100755 list_droplets.sh diff --git a/dospin.go b/dospin.go index aab92c0..5bc86b7 100644 --- a/dospin.go +++ b/dospin.go @@ -33,6 +33,11 @@ func main() { return } log.Println("IP: " + ip) + + if err := dm.SpindownMachine("minecraft"); err != nil { + log.Println("Error:", err) + return + } //_, err = client.Droplets.Delete(droplet.ID) //if err != nil { // log.Println(err) diff --git a/dropletmanager.go b/dropletmanager.go index df2a1a0..fac0072 100644 --- a/dropletmanager.go +++ b/dropletmanager.go @@ -3,6 +3,7 @@ package main import ( "errors" "github.com/digitalocean/godo" + "log" "time" ) @@ -27,6 +28,7 @@ func (me *DropletManager) SpinupMachine(name string) (string, error) { if droplet, err := me.getDroplet(name); err == nil { return droplet.PrivateIPv4() } else { + // create the droplet image, err := me.getSnapshot(name) if err != nil { return "", err @@ -42,23 +44,75 @@ func (me *DropletManager) SpinupMachine(name string) (string, error) { }, } - _, _, err = me.client.Droplets.Create(createRequest) + log.Println("Spinup: Creating " + name) + droplet, _, err := me.client.Droplets.Create(createRequest) + // wait until machine is ready + for { + d, _, err := me.client.Droplets.Get(droplet.ID) + if err != nil { + log.Println(err) + } else if d.Status == "active" { + break + } + time.Sleep(500 * time.Millisecond) + } if err != nil { return "", err } + log.Println("Spinup: Created " + name) // get the private IP and return it - ip := "" + droplet, _, err = me.client.Droplets.Get(droplet.ID) + if err != nil { + return "", err + } + return droplet.PrivateIPv4() + } +} + +func (me *DropletManager) SpindownMachine(name string) error { + droplet, err := me.getDroplet(name) + if err != nil { + return err + } + + // power off + if droplet.Status != "off" { + log.Println("Spindown: Powering down " + name) + // wait until machine is off for { droplet, err = me.getDroplet(name) - ip, err = droplet.PrivateIPv4() - if ip != "" || (err != nil && err.Error() != "no networks have been defined") { + if err != nil { + log.Println(err) + } else if droplet.Status == "off" { break } time.Sleep(100 * time.Millisecond) + _, _, err = me.client.DropletActions.Shutdown(droplet.ID) + if err != nil { + log.Println("Power down of ", name, " failed: ", err) + } } - return ip, err + log.Println("Spindown: Powered down " + name) } + + // snapshot existing droplet + log.Println("Spindown: Snapshoting " + name) + action, _, err := me.client.DropletActions.Snapshot(droplet.ID, DROPLET_NS+name) + if err != nil || !me.actionWait(action.ID) { + return err + } + log.Println("Spindown: Snapshoted " + name) + + // delete droplet + log.Println("Spindown: Deleting " + name) + _, err = me.client.Droplets.Delete(droplet.ID) + if err != nil { + return err + } + log.Println("Spindown: Deleted " + name) + + return err } func (me *DropletManager) getDroplet(name string) (godo.Droplet, error) { @@ -125,3 +179,19 @@ func (me *DropletManager) getSnapshot(name string) (godo.Image, error) { } return image, err } + +func (me *DropletManager) actionWait(actionId int) bool { + for { + a, _, err := me.client.Actions.Get(actionId) + if err != nil { + log.Println("Action failed: ", err) + return false + } else if a.Status == "completed" { + return true + } else if a.Status == "errored" { + log.Println("Action failed: ", a.Type, " on ", a.ResourceID) + return false + } + time.Sleep(1000 * time.Millisecond) + } +} diff --git a/list_droplets.sh b/list_droplets.sh new file mode 100755 index 0000000..77cb83f --- /dev/null +++ b/list_droplets.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env sh +curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer `cat dospin.json | jq -r .Token`" "https://api.digitalocean.com/v2/droplets?page=1&per_page=100&private=true" | jq .