/
results.go
367 lines (295 loc) · 9.16 KB
/
results.go
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
package hypervisors
import (
"encoding/json"
"fmt"
"strconv"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
// Topology represents a CPU Topology.
type Topology struct {
Sockets int `json:"sockets"`
Cores int `json:"cores"`
Threads int `json:"threads"`
}
// CPUInfo represents CPU information of the hypervisor.
type CPUInfo struct {
Vendor string `json:"vendor"`
Arch string `json:"arch"`
Model string `json:"model"`
Features []string `json:"features"`
Topology Topology `json:"topology"`
}
// Service represents a Compute service running on the hypervisor.
type Service struct {
Host string `json:"host"`
ID string `json:"-"`
DisabledReason string `json:"disabled_reason"`
}
func (r *Service) UnmarshalJSON(b []byte) error {
type tmp Service
var s struct {
tmp
ID interface{} `json:"id"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = Service(s.tmp)
// OpenStack Compute service returns ID in string representation since
// 2.53 microversion API (Pike release).
switch t := s.ID.(type) {
case int:
r.ID = strconv.Itoa(t)
case float64:
r.ID = strconv.Itoa(int(t))
case string:
r.ID = t
default:
return fmt.Errorf("ID has unexpected type: %T", t)
}
return nil
}
// Hypervisor represents a hypervisor in the OpenStack cloud.
type Hypervisor struct {
// A structure that contains cpu information like arch, model, vendor,
// features and topology.
CPUInfo CPUInfo `json:"-"`
// The current_workload is the number of tasks the hypervisor is responsible
// for. This will be equal or greater than the number of active VMs on the
// system (it can be greater when VMs are being deleted and the hypervisor is
// still cleaning up).
CurrentWorkload int `json:"current_workload"`
// Status of the hypervisor, either "enabled" or "disabled".
Status string `json:"status"`
// State of the hypervisor, either "up" or "down".
State string `json:"state"`
// DiskAvailableLeast is the actual free disk on this hypervisor,
// measured in GB.
DiskAvailableLeast int `json:"disk_available_least"`
// HostIP is the hypervisor's IP address.
HostIP string `json:"host_ip"`
// FreeDiskGB is the free disk remaining on the hypervisor, measured in GB.
FreeDiskGB int `json:"-"`
// FreeRAMMB is the free RAM in the hypervisor, measured in MB.
FreeRamMB int `json:"free_ram_mb"`
// HypervisorHostname is the hostname of the hypervisor.
HypervisorHostname string `json:"hypervisor_hostname"`
// HypervisorType is the type of hypervisor.
HypervisorType string `json:"hypervisor_type"`
// HypervisorVersion is the version of the hypervisor.
HypervisorVersion int `json:"-"`
// ID is the unique ID of the hypervisor.
ID string `json:"-"`
// LocalGB is the disk space in the hypervisor, measured in GB.
LocalGB int `json:"-"`
// LocalGBUsed is the used disk space of the hypervisor, measured in GB.
LocalGBUsed int `json:"local_gb_used"`
// MemoryMB is the total memory of the hypervisor, measured in MB.
MemoryMB int `json:"memory_mb"`
// MemoryMBUsed is the used memory of the hypervisor, measured in MB.
MemoryMBUsed int `json:"memory_mb_used"`
// RunningVMs is the The number of running vms on the hypervisor.
RunningVMs int `json:"running_vms"`
// Service is the service this hypervisor represents.
Service Service `json:"service"`
// VCPUs is the total number of vcpus on the hypervisor.
VCPUs int `json:"vcpus"`
// VCPUsUsed is the number of used vcpus on the hypervisor.
VCPUsUsed int `json:"vcpus_used"`
}
func (r *Hypervisor) UnmarshalJSON(b []byte) error {
type tmp Hypervisor
var s struct {
tmp
ID interface{} `json:"id"`
CPUInfo interface{} `json:"cpu_info"`
HypervisorVersion interface{} `json:"hypervisor_version"`
FreeDiskGB interface{} `json:"free_disk_gb"`
LocalGB interface{} `json:"local_gb"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = Hypervisor(s.tmp)
// Newer versions return the CPU info as the correct type.
// Older versions return the CPU info as a string and need to be
// unmarshalled by the json parser.
var tmpb []byte
switch t := s.CPUInfo.(type) {
case string:
tmpb = []byte(t)
case map[string]interface{}:
tmpb, err = json.Marshal(t)
if err != nil {
return err
}
default:
return fmt.Errorf("CPUInfo has unexpected type: %T", t)
}
if len(tmpb) != 0 {
err = json.Unmarshal(tmpb, &r.CPUInfo)
if err != nil {
return err
}
}
// These fields may be returned as a scientific notation, so they need
// converted to int.
switch t := s.HypervisorVersion.(type) {
case int:
r.HypervisorVersion = t
case float64:
r.HypervisorVersion = int(t)
default:
return fmt.Errorf("Hypervisor version has unexpected type: %T", t)
}
switch t := s.FreeDiskGB.(type) {
case int:
r.FreeDiskGB = t
case float64:
r.FreeDiskGB = int(t)
default:
return fmt.Errorf("Free disk GB has unexpected type: %T", t)
}
switch t := s.LocalGB.(type) {
case int:
r.LocalGB = t
case float64:
r.LocalGB = int(t)
default:
return fmt.Errorf("Local GB has unexpected type: %T", t)
}
// OpenStack Compute service returns ID in string representation since
// 2.53 microversion API (Pike release).
switch t := s.ID.(type) {
case int:
r.ID = strconv.Itoa(t)
case float64:
r.ID = strconv.Itoa(int(t))
case string:
r.ID = t
default:
return fmt.Errorf("ID has unexpected type: %T", t)
}
return nil
}
// HypervisorPage represents a single page of all Hypervisors from a List
// request.
type HypervisorPage struct {
pagination.SinglePageBase
}
// IsEmpty determines whether or not a HypervisorPage is empty.
func (page HypervisorPage) IsEmpty() (bool, error) {
va, err := ExtractHypervisors(page)
return len(va) == 0, err
}
// ExtractHypervisors interprets a page of results as a slice of Hypervisors.
func ExtractHypervisors(p pagination.Page) ([]Hypervisor, error) {
var h struct {
Hypervisors []Hypervisor `json:"hypervisors"`
}
err := (p.(HypervisorPage)).ExtractInto(&h)
return h.Hypervisors, err
}
type HypervisorResult struct {
gophercloud.Result
}
// Extract interprets any HypervisorResult as a Hypervisor, if possible.
func (r HypervisorResult) Extract() (*Hypervisor, error) {
var s struct {
Hypervisor Hypervisor `json:"hypervisor"`
}
err := r.ExtractInto(&s)
return &s.Hypervisor, err
}
// Statistics represents a summary statistics for all enabled
// hypervisors over all compute nodes in the OpenStack cloud.
type Statistics struct {
// The number of hypervisors.
Count int `json:"count"`
// The current_workload is the number of tasks the hypervisor is responsible for
CurrentWorkload int `json:"current_workload"`
// The actual free disk on this hypervisor(in GB).
DiskAvailableLeast int `json:"disk_available_least"`
// The free disk remaining on this hypervisor(in GB).
FreeDiskGB int `json:"free_disk_gb"`
// The free RAM in this hypervisor(in MB).
FreeRamMB int `json:"free_ram_mb"`
// The disk in this hypervisor(in GB).
LocalGB int `json:"local_gb"`
// The disk used in this hypervisor(in GB).
LocalGBUsed int `json:"local_gb_used"`
// The memory of this hypervisor(in MB).
MemoryMB int `json:"memory_mb"`
// The memory used in this hypervisor(in MB).
MemoryMBUsed int `json:"memory_mb_used"`
// The total number of running vms on all hypervisors.
RunningVMs int `json:"running_vms"`
// The number of vcpu in this hypervisor.
VCPUs int `json:"vcpus"`
// The number of vcpu used in this hypervisor.
VCPUsUsed int `json:"vcpus_used"`
}
type StatisticsResult struct {
gophercloud.Result
}
// Extract interprets any StatisticsResult as a Statistics, if possible.
func (r StatisticsResult) Extract() (*Statistics, error) {
var s struct {
Stats Statistics `json:"hypervisor_statistics"`
}
err := r.ExtractInto(&s)
return &s.Stats, err
}
// Uptime represents uptime and additional info for a specific hypervisor.
type Uptime struct {
// The hypervisor host name provided by the Nova virt driver.
// For the Ironic driver, it is the Ironic node uuid.
HypervisorHostname string `json:"hypervisor_hostname"`
// The id of the hypervisor.
ID string `json:"-"`
// The state of the hypervisor. One of up or down.
State string `json:"state"`
// The status of the hypervisor. One of enabled or disabled.
Status string `json:"status"`
// The total uptime of the hypervisor and information about average load.
Uptime string `json:"uptime"`
}
func (r *Uptime) UnmarshalJSON(b []byte) error {
type tmp Uptime
var s struct {
tmp
ID interface{} `json:"id"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = Uptime(s.tmp)
// OpenStack Compute service returns ID in string representation since
// 2.53 microversion API (Pike release).
switch t := s.ID.(type) {
case int:
r.ID = strconv.Itoa(t)
case float64:
r.ID = strconv.Itoa(int(t))
case string:
r.ID = t
default:
return fmt.Errorf("ID has unexpected type: %T", t)
}
return nil
}
type UptimeResult struct {
gophercloud.Result
}
// Extract interprets any UptimeResult as a Uptime, if possible.
func (r UptimeResult) Extract() (*Uptime, error) {
var s struct {
Uptime Uptime `json:"hypervisor"`
}
err := r.ExtractInto(&s)
return &s.Uptime, err
}