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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
package virtpb
import (
// "reflect"
"errors"
"fmt"
"time"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
"go.wit.com/log"
)
func convertToAnypb(x any) *anypb.Any {
switch v := x.(type) {
case int64:
var a *anypb.Any
a, _ = anypb.New(wrapperspb.Int64(x.(int64)))
return a
case string:
var a *anypb.Any
a, _ = anypb.New(wrapperspb.String(x.(string)))
return a
case int:
var a *anypb.Any
a, _ = anypb.New(wrapperspb.Int64(x.(int64)))
return a
case bool:
var a *anypb.Any
a, _ = anypb.New(wrapperspb.Bool(x.(bool)))
return a
default:
log.Error(errors.New("convertToAnypb() unknown type"), "v =", v, "x =", x)
}
return nil
}
func convertToString(x any) string {
switch v := x.(type) {
case int64:
return fmt.Sprintf("%d", x.(int64))
case string:
return x.(string)
case int:
return fmt.Sprintf("%d", x.(int))
case uint:
return fmt.Sprintf("%d", x.(uint))
case *DropletState:
var s *DropletState
s = x.(*DropletState)
return s.String()
case DropletState:
var s DropletState
s = x.(DropletState)
return s.String()
case bool:
if x.(bool) {
return "true"
}
return "false"
default:
log.Info("convertToSTring() unknown type", v)
log.Error(errors.New("convertToSTring() unknown type"), "v =", v, "x =", x)
}
return ""
}
// Wrapping the int into a protobuf message
func (d *Droplet) NewChangeEvent(fname string, origval any, newval any) *Event {
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.OrigVal = convertToString(origval)
e.NewVal = convertToString(newval)
e.FieldName = fname
now := time.Now()
e.Start = timestamppb.New(now)
// this also works, but it's a bit overkill
// e.NewAny = convertToAnypb(newval)
// me.events.Events = append(me.events.Events, e)
// stuff := me.events.FormatJSON()
// log.Info("events:", stuff)
return e
}
// work in progress
func NewAddEvent(a any, fname string, newval any) *Event {
var e *Event
e = new(Event)
switch v := a.(type) {
case *Droplet:
var d *Droplet
d = a.(*Droplet)
e.Droplet = d.Hostname
case nil:
e.Droplet = "<nil>"
default:
log.Info("newAddEvent() unknown type", v)
e.Droplet = "on something somewhere"
}
e.NewVal = convertToString(newval)
e.FieldName = fname
now := time.Now()
e.Start = timestamppb.New(now)
return e
}
// update the droplet memory
func (d *Droplet) SetMemory(b int64) *Event {
oldm := HumanFormatBytes(d.Memory)
newm := HumanFormatBytes(b)
if d.Memory == b {
// log.Info("droplet", d.Hostname, "memory unchanged", oldm, "to", newm)
return nil
}
log.Info("droplet", d.Hostname, "memory change from", oldm, "to", newm)
return d.NewChangeEvent("Droplet.Memory", d.Memory, b)
}
// update the droplet memory
func (d *Droplet) SetCpus(b int64) {
log.Info("Set the number of cpus for the droplet", b)
}
// update the droplet memory
func (d *Droplet) SetState(newState DropletState) {
if d.Current == nil {
d.Current = new(Current)
}
if d.Current.State == newState {
// nothing has changed
return
}
switch newState {
case DropletState_ON:
d.Current.OnSince = timestamppb.New(time.Now())
d.Current.OffSince = nil
case DropletState_OFF:
d.Current.OffSince = timestamppb.New(time.Now())
d.Current.OnSince = nil
default:
// zero on OnSince to indicate something hickup'd?
// not sure if this should be done here. probably trust qemu dom0 instead
// but I can't do that right now so for now this will work
d.Current.OnSince = timestamppb.New(time.Now())
d.Current.OffSince = timestamppb.New(time.Now())
}
d.Current.State = newState
d.NewChangeEvent("STATE", d.Current.State, newState)
log.Info("Droplet", d.Hostname, "changed state from", d.Current.State, "to", newState)
}
// records an event that the droplet changed state (aka turned on, turned off, etc)
func (c *OldCluster) ChangeDropletState(d *Droplet, newState DropletState) error {
if c == nil {
return errors.New("cluster is nil")
}
if d == nil {
return errors.New("droplet is nil")
}
if d.Current.State == newState {
// droplet status didn't change
return nil
}
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.OrigVal = convertToString(d.Current.State)
e.NewVal = convertToString(newState)
e.FieldName = "status"
now := time.Now()
e.Start = timestamppb.New(now)
c.e.Events = append(c.e.Events, e)
return nil
}
// records an event that the droplet migrated to another hypervisor
func (c *OldCluster) DropletMoved(d *Droplet, newh *Hypervisor) error {
if c == nil {
return errors.New("cluster is nil")
}
if d == nil {
return errors.New("droplet is nil")
}
if newh == nil {
return errors.New("hypervisor is nil")
}
if d.Current.Hypervisor == newh.Hostname {
// droplet didn't move
return nil
}
// make a change event
var e *Event
e = new(Event)
e.Droplet = d.Hostname
e.OrigVal = d.Current.Hypervisor
e.NewVal = newh.Hostname
e.FieldName = "droplet migrate"
now := time.Now()
e.Start = timestamppb.New(now)
c.e.Events = append(c.e.Events, e)
// update the droplet record
d.Current.Hypervisor = newh.Hostname
return nil
}
|