1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
package main
import (
"errors"
"fmt"
"math/rand"
"time"
pb "go.wit.com/lib/protobuf/virtbuf"
)
// attempts to create a new virtual machine
/*
func oldcreate(w http.ResponseWriter, r *http.Request) (string, error) {
msg, err := ioutil.ReadAll(r.Body) // Read the body as []byte
if err != nil {
result := fmt.Sprintf("ReadAll() error =", err)
log.Info(result)
fmt.Fprintln(w, result)
return result, err
}
var d *pb.Droplet
d = new(pb.Droplet)
if err := d.UnmarshalJSON(msg); err != nil {
log.Info("UnmarshalJSON() failed", err)
if err := d.Unmarshal(msg); err != nil {
log.Info("droplet protobuf.Unmarshal() failed", err)
return "", err
}
}
d.StartState = pb.DropletState_OFF
d.SetState(pb.DropletState_OFF)
d.Memory = 2048 * 1024 * 1024
d.Cpus = 2
log.Info("Got msg:", string(msg))
log.Info("hostname =", d.Hostname)
name := d.Hostname
// don't continue past here if the grid is unstable anyway
// because this will add the droplet to cluster.Droplets
if s, err := isClusterStable(); err != nil {
log.Info(s)
fmt.Fprintln(w, s)
return s, err
}
tmpd := me.cluster.FindDropletByName(name)
if tmpd != nil {
result := "create error: Droplet " + name + " is already defined"
log.Info(result)
fmt.Fprintln(w, result)
return result, errors.New(result)
}
if d.Uuid == "" {
u := uuid.New()
d.Uuid = u.String()
}
if len(d.Networks) == 0 {
var newNet *pb.Network
newNet = new(pb.Network)
newNet.Mac = getNewMac()
d.Networks = append(d.Networks, newNet)
// d.AddDefaultNetwork(mac)
}
me.cluster.AddDroplet(d)
result, err := startDroplet(d)
if err != nil {
log.Info(result)
log.Info("startDroplet(d) failed:", err)
fmt.Fprintln(w, result)
fmt.Fprintln(w, "startDroplet(d) failed:", err)
return result, err
}
fmt.Fprintln(w, result)
fmt.Fprintln(w, "START=OK")
return result, nil
}
*/
// for now, because sometimes this should write to stdout and
// sometimes to http socket, it returns a string
func startDroplet(d *pb.Droplet) (string, error) {
var result string
name := d.Hostname
// validate the droplet
if err := ValidateDroplet(d); err != nil {
result = "ValidateDroplet() failed droplet " + d.Hostname
return result, err
}
// is the droplet already on?
if d.Current.State == pb.DropletState_ON {
result = "EVENT start droplet " + d.Hostname + " is already ON"
return result, errors.New(result)
}
// how long has the cluster been stable?
// wait until it is stable. use this to throttle droplet starts
dur := time.Since(me.unstable)
result = fmt.Sprintln("should start droplet", name, "here. grid stable for:", pb.FormatDuration(dur))
if dur < me.unstableTimeout {
tmp := pb.FormatDuration(me.unstableTimeout)
result += "grid is still too unstable (unstable timeout = " + tmp + ")"
return result, errors.New("grid is still unstable")
}
// make the list of hypervisors that are active and can start new droplets
var pool []*HyperT
for _, h := range me.hypers {
// this droplet is set to use this and only this hypervisor
if d.ForceHypervisor == h.pb.Hostname {
ok, b := h.start(d)
if ok {
return result + b, nil
}
return result + b, errors.New("start " + name + " on hypervisor " + h.pb.Hostname)
}
// skip hypervisors marked inactive
if h.pb.Active != true {
result += fmt.Sprintln("hypervisor is inactive:", name, "for", h.pb.Hostname, h.pb.Active)
continue
}
// the config file says this droplet should run on this hypervisor
// attempt to start the droplet here. use this even if the hypervisor is inactive?
if d.PreferredHypervisor == h.pb.Hostname {
ok, b := h.start(d)
if ok {
return result + b, nil
}
return result + b, errors.New("start " + name + " on hypervisor " + h.pb.Hostname)
}
result += fmt.Sprintln("hypervisor ready:", name, "for", h.pb.Hostname, h.pb.Active)
pool = append(pool, h)
}
// left here as an example of how to actually do random numbers
// it's complete mathematical chaos. Randomness is simple when
// human interaction occurs -- which is exactly what happens most
// of the time. most random shit is bullshit. all you really need
// is exactly this to make sure the random functions work as they
// should. Probably, just use this everywhere in all cases. --jcarr
rand.Seed(time.Now().UnixNano())
a := 0
b := len(pool)
n := a + rand.Intn(b-a)
result += fmt.Sprintln("pool has", len(pool), "members", "rand =", n)
h := pool[n]
ok, output := h.start(d)
if ok {
return result + output, nil
}
return result + output, errors.New("start " + name + " on hypervisor " + h.pb.Hostname)
}
|