blob: a72ed7e54e40d7db03a4b08ded27e795c828bc60 [file] [log] [blame]
Simon Murraya9d5de42016-11-03 15:06:44 +00001package hypervisors
2
3import (
4 "encoding/json"
5 "fmt"
Krzysztof Szukiełojć2f616852017-05-12 16:24:00 +02006
Krzysztof Szukiełojć24a29ce2017-05-07 14:24:02 +02007 "gerrit.mcp.mirantis.net/debian/gophercloud.git/pagination"
Simon Murraya9d5de42016-11-03 15:06:44 +00008)
9
10type Topology struct {
11 Sockets int `json:"sockets"`
12 Cores int `json:"cores"`
13 Threads int `json:"threads"`
14}
15
16type CPUInfo struct {
17 Vendor string `json:"vendor"`
18 Arch string `json:"arch"`
19 Model string `json:"model"`
20 Features []string `json:"features"`
21 Topology Topology `json:"topology"`
22}
23
24type Service struct {
25 Host string `json:"host"`
26 ID int `json:"id"`
27 DisabledReason string `json:"disabled_reason"`
28}
29
30type Hypervisor struct {
31 // A structure that contains cpu information like arch, model, vendor, features and topology
32 CPUInfo CPUInfo `json:"-"`
33 // The current_workload is the number of tasks the hypervisor is responsible for.
34 // This will be equal or greater than the number of active VMs on the system
35 // (it can be greater when VMs are being deleted and the hypervisor is still cleaning up).
36 CurrentWorkload int `json:"current_workload"`
37 // Status of the hypervisor, either "enabled" or "disabled"
38 Status string `json:"status"`
39 // State of the hypervisor, either "up" or "down"
40 State string `json:"state"`
41 // Actual free disk on this hypervisor in GB
42 DiskAvailableLeast int `json:"disk_available_least"`
43 // The hypervisor's IP address
44 HostIP string `json:"host_ip"`
45 // The free disk remaining on this hypervisor in GB
46 FreeDiskGB int `json:"-"`
47 // The free RAM in this hypervisor in MB
48 FreeRamMB int `json:"free_ram_mb"`
49 // The hypervisor host name
50 HypervisorHostname string `json:"hypervisor_hostname"`
51 // The hypervisor type
52 HypervisorType string `json:"hypervisor_type"`
53 // The hypervisor version
54 HypervisorVersion int `json:"-"`
55 // Unique ID of the hypervisor
56 ID int `json:"id"`
57 // The disk in this hypervisor in GB
58 LocalGB int `json:"-"`
59 // The disk used in this hypervisor in GB
60 LocalGBUsed int `json:"local_gb_used"`
61 // The memory of this hypervisor in MB
62 MemoryMB int `json:"memory_mb"`
63 // The memory used in this hypervisor in MB
64 MemoryMBUsed int `json:"memory_mb_used"`
65 // The number of running vms on this hypervisor
66 RunningVMs int `json:"running_vms"`
67 // The hypervisor service object
68 Service Service `json:"service"`
69 // The number of vcpu in this hypervisor
70 VCPUs int `json:"vcpus"`
71 // The number of vcpu used in this hypervisor
72 VCPUsUsed int `json:"vcpus_used"`
73}
74
Krzysztof Szukiełojć2f616852017-05-12 16:24:00 +020075type Aggregate struct {
76 Name string `json:name`
77 Hosts []string `json:hosts`
78 ID int `json:id`
Simon Murraya9d5de42016-11-03 15:06:44 +000079}
80
81func (r *Hypervisor) UnmarshalJSON(b []byte) error {
82
83 type tmp Hypervisor
84 var s *struct {
85 tmp
86 CPUInfo interface{} `json:"cpu_info"`
87 HypervisorVersion interface{} `json:"hypervisor_version"`
88 FreeDiskGB interface{} `json:"free_disk_gb"`
89 LocalGB interface{} `json:"local_gb"`
90 }
91
92 err := json.Unmarshal(b, &s)
93 if err != nil {
94 return err
95 }
96
97 *r = Hypervisor(s.tmp)
98
99 // Newer versions pass the CPU into around as the correct types, this just needs
100 // converting and copying into place. Older versions pass CPU info around as a string
101 // and can simply be unmarshalled by the json parser
Krzysztof Szukiełojć2f616852017-05-12 16:24:00 +0200102 var tmpb []byte
Simon Murraya9d5de42016-11-03 15:06:44 +0000103
104 switch t := s.CPUInfo.(type) {
105 case string:
106 tmpb = []byte(t)
107 case map[string]interface{}:
108 tmpb, err = json.Marshal(t)
109 if err != nil {
110 return err
111 }
112 default:
113 return fmt.Errorf("CPUInfo has unexpected type: %T", t)
114 }
Ildar Svetlovde934122018-11-02 17:34:39 +0400115 if len(tmpb) > 0 {
116 err = json.Unmarshal(tmpb, &r.CPUInfo)
117 if err != nil {
118 return err
119 }
Simon Murraya9d5de42016-11-03 15:06:44 +0000120 }
121
122 // These fields may be passed in in scientific notation
123 switch t := s.HypervisorVersion.(type) {
124 case int:
125 r.HypervisorVersion = t
126 case float64:
127 r.HypervisorVersion = int(t)
128 default:
129 return fmt.Errorf("Hypervisor version of unexpected type")
130 }
131
132 switch t := s.FreeDiskGB.(type) {
133 case int:
134 r.FreeDiskGB = t
135 case float64:
136 r.FreeDiskGB = int(t)
137 default:
138 return fmt.Errorf("Free disk GB of unexpected type")
139 }
140
141 switch t := s.LocalGB.(type) {
142 case int:
143 r.LocalGB = t
144 case float64:
145 r.LocalGB = int(t)
146 default:
147 return fmt.Errorf("Local GB of unexpected type")
148 }
149
150 return nil
151}
152
153type HypervisorPage struct {
154 pagination.SinglePageBase
155}
156
157func (page HypervisorPage) IsEmpty() (bool, error) {
Krzysztof Szukiełojć2f616852017-05-12 16:24:00 +0200158 va, err := ExtractHypervisors(page)
159 return len(va) == 0, err
Simon Murraya9d5de42016-11-03 15:06:44 +0000160}
161
162func ExtractHypervisors(p pagination.Page) ([]Hypervisor, error) {
163 var h struct {
164 Hypervisors []Hypervisor `json:"hypervisors"`
165 }
166 err := (p.(HypervisorPage)).ExtractInto(&h)
167 return h.Hypervisors, err
168}
169
170func ExtractAggregates(p pagination.Page) ([]Aggregate, error) {
171 var h struct {
172 Aggregates []Aggregate `json:"aggregates"`
173 }
Simon Murraya9d5de42016-11-03 15:06:44 +0000174 err := (p.(AggregatePage)).ExtractInto(&h)
175 return h.Aggregates, err
176}
177
178type AggregatePage struct {
Krzysztof Szukiełojć2f616852017-05-12 16:24:00 +0200179 pagination.SinglePageBase
Simon Murraya9d5de42016-11-03 15:06:44 +0000180}