github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/compute/v2/hypervisors/results.go (about) 1 package hypervisors 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strconv" 7 8 "github.com/vnpaycloud-console/gophercloud/v2" 9 "github.com/vnpaycloud-console/gophercloud/v2/pagination" 10 ) 11 12 // Topology represents a CPU Topology. 13 type Topology struct { 14 Sockets int `json:"sockets"` 15 Cores int `json:"cores"` 16 Threads int `json:"threads"` 17 } 18 19 // CPUInfo represents CPU information of the hypervisor. 20 type CPUInfo struct { 21 Vendor string `json:"vendor"` 22 Arch string `json:"arch"` 23 Model string `json:"model"` 24 Features []string `json:"features"` 25 Topology Topology `json:"topology"` 26 } 27 28 // Service represents a Compute service running on the hypervisor. 29 type Service struct { 30 Host string `json:"host"` 31 ID string `json:"-"` 32 DisabledReason string `json:"disabled_reason"` 33 } 34 35 func (r *Service) UnmarshalJSON(b []byte) error { 36 type tmp Service 37 var s struct { 38 tmp 39 ID any `json:"id"` 40 } 41 42 err := json.Unmarshal(b, &s) 43 if err != nil { 44 return err 45 } 46 47 *r = Service(s.tmp) 48 49 // OpenStack Compute service returns ID in string representation since 50 // 2.53 microversion API (Pike release). 51 switch t := s.ID.(type) { 52 case int: 53 r.ID = strconv.Itoa(t) 54 case float64: 55 r.ID = strconv.Itoa(int(t)) 56 case string: 57 r.ID = t 58 default: 59 return fmt.Errorf("ID has unexpected type: %T", t) 60 } 61 62 return nil 63 } 64 65 // Server represents an instance running on the hypervisor 66 type Server struct { 67 Name string `json:"name"` 68 UUID string `json:"uuid"` 69 } 70 71 // Hypervisor represents a hypervisor in the OpenStack cloud. 72 type Hypervisor struct { 73 // A structure that contains cpu information like arch, model, vendor, 74 // features and topology. 75 CPUInfo CPUInfo `json:"-"` 76 77 // The current_workload is the number of tasks the hypervisor is responsible 78 // for. This will be equal or greater than the number of active VMs on the 79 // system (it can be greater when VMs are being deleted and the hypervisor is 80 // still cleaning up). 81 CurrentWorkload int `json:"current_workload"` 82 83 // Status of the hypervisor, either "enabled" or "disabled". 84 Status string `json:"status"` 85 86 // State of the hypervisor, either "up" or "down". 87 State string `json:"state"` 88 89 // DiskAvailableLeast is the actual free disk on this hypervisor, 90 // measured in GB. 91 DiskAvailableLeast int `json:"disk_available_least"` 92 93 // HostIP is the hypervisor's IP address. 94 HostIP string `json:"host_ip"` 95 96 // FreeDiskGB is the free disk remaining on the hypervisor, measured in GB. 97 FreeDiskGB int `json:"-"` 98 99 // FreeRAMMB is the free RAM in the hypervisor, measured in MB. 100 FreeRamMB int `json:"free_ram_mb"` 101 102 // HypervisorHostname is the hostname of the hypervisor. 103 HypervisorHostname string `json:"hypervisor_hostname"` 104 105 // HypervisorType is the type of hypervisor. 106 HypervisorType string `json:"hypervisor_type"` 107 108 // HypervisorVersion is the version of the hypervisor. 109 HypervisorVersion int `json:"-"` 110 111 // ID is the unique ID of the hypervisor. 112 ID string `json:"-"` 113 114 // LocalGB is the disk space in the hypervisor, measured in GB. 115 LocalGB int `json:"-"` 116 117 // LocalGBUsed is the used disk space of the hypervisor, measured in GB. 118 LocalGBUsed int `json:"local_gb_used"` 119 120 // MemoryMB is the total memory of the hypervisor, measured in MB. 121 MemoryMB int `json:"memory_mb"` 122 123 // MemoryMBUsed is the used memory of the hypervisor, measured in MB. 124 MemoryMBUsed int `json:"memory_mb_used"` 125 126 // RunningVMs is the The number of running vms on the hypervisor. 127 RunningVMs int `json:"running_vms"` 128 129 // Service is the service this hypervisor represents. 130 Service Service `json:"service"` 131 132 // Servers is a list of Server object. 133 // The requires microversion 2.53 or later. 134 Servers *[]Server `json:"servers"` 135 136 // VCPUs is the total number of vcpus on the hypervisor. 137 VCPUs int `json:"vcpus"` 138 139 // VCPUsUsed is the number of used vcpus on the hypervisor. 140 VCPUsUsed int `json:"vcpus_used"` 141 } 142 143 func (r *Hypervisor) UnmarshalJSON(b []byte) error { 144 type tmp Hypervisor 145 var s struct { 146 tmp 147 ID any `json:"id"` 148 CPUInfo any `json:"cpu_info"` 149 HypervisorVersion any `json:"hypervisor_version"` 150 FreeDiskGB any `json:"free_disk_gb"` 151 LocalGB any `json:"local_gb"` 152 } 153 154 err := json.Unmarshal(b, &s) 155 if err != nil { 156 return err 157 } 158 159 *r = Hypervisor(s.tmp) 160 161 // cpu_info doesn't exist after api version 2.87, 162 // see https://docs.openstack.org/api-ref/compute/#id288 163 if s.CPUInfo != nil { 164 // api versions 2.28 to 2.87 return the CPU info as the correct type. 165 // api versions < 2.28 return the CPU info as a string and need to be 166 // unmarshalled by the json parser. 167 var tmpb []byte 168 169 switch t := s.CPUInfo.(type) { 170 case string: 171 tmpb = []byte(t) 172 case map[string]any: 173 tmpb, err = json.Marshal(t) 174 if err != nil { 175 return err 176 } 177 default: 178 return fmt.Errorf("CPUInfo has unexpected type: %T", t) 179 } 180 181 if len(tmpb) != 0 { 182 err = json.Unmarshal(tmpb, &r.CPUInfo) 183 if err != nil { 184 return err 185 } 186 } 187 } 188 189 // These fields may be returned as a scientific notation, so they need 190 // converted to int. 191 switch t := s.HypervisorVersion.(type) { 192 case int: 193 r.HypervisorVersion = t 194 case float64: 195 r.HypervisorVersion = int(t) 196 default: 197 return fmt.Errorf("Hypervisor version has unexpected type: %T", t) 198 } 199 200 // free_disk_gb doesn't exist after api version 2.87 201 if s.FreeDiskGB != nil { 202 switch t := s.FreeDiskGB.(type) { 203 case int: 204 r.FreeDiskGB = t 205 case float64: 206 r.FreeDiskGB = int(t) 207 default: 208 return fmt.Errorf("Free disk GB has unexpected type: %T", t) 209 } 210 } 211 212 // local_gb doesn't exist after api version 2.87 213 if s.LocalGB != nil { 214 switch t := s.LocalGB.(type) { 215 case int: 216 r.LocalGB = t 217 case float64: 218 r.LocalGB = int(t) 219 default: 220 return fmt.Errorf("Local GB has unexpected type: %T", t) 221 } 222 } 223 224 // OpenStack Compute service returns ID in string representation since 225 // 2.53 microversion API (Pike release). 226 switch t := s.ID.(type) { 227 case int: 228 r.ID = strconv.Itoa(t) 229 case float64: 230 r.ID = strconv.Itoa(int(t)) 231 case string: 232 r.ID = t 233 default: 234 return fmt.Errorf("ID has unexpected type: %T", t) 235 } 236 237 return nil 238 } 239 240 // HypervisorPage represents a single page of all Hypervisors from a List 241 // request. 242 type HypervisorPage struct { 243 pagination.SinglePageBase 244 } 245 246 // IsEmpty determines whether or not a HypervisorPage is empty. 247 func (page HypervisorPage) IsEmpty() (bool, error) { 248 if page.StatusCode == 204 { 249 return true, nil 250 } 251 252 va, err := ExtractHypervisors(page) 253 return len(va) == 0, err 254 } 255 256 // ExtractHypervisors interprets a page of results as a slice of Hypervisors. 257 func ExtractHypervisors(p pagination.Page) ([]Hypervisor, error) { 258 var h struct { 259 Hypervisors []Hypervisor `json:"hypervisors"` 260 } 261 err := (p.(HypervisorPage)).ExtractInto(&h) 262 return h.Hypervisors, err 263 } 264 265 type HypervisorResult struct { 266 gophercloud.Result 267 } 268 269 // Extract interprets any HypervisorResult as a Hypervisor, if possible. 270 func (r HypervisorResult) Extract() (*Hypervisor, error) { 271 var s struct { 272 Hypervisor Hypervisor `json:"hypervisor"` 273 } 274 err := r.ExtractInto(&s) 275 return &s.Hypervisor, err 276 } 277 278 // Statistics represents a summary statistics for all enabled 279 // hypervisors over all compute nodes in the OpenStack cloud. 280 type Statistics struct { 281 // The number of hypervisors. 282 Count int `json:"count"` 283 284 // The current_workload is the number of tasks the hypervisor is responsible for 285 CurrentWorkload int `json:"current_workload"` 286 287 // The actual free disk on this hypervisor(in GB). 288 DiskAvailableLeast int `json:"disk_available_least"` 289 290 // The free disk remaining on this hypervisor(in GB). 291 FreeDiskGB int `json:"free_disk_gb"` 292 293 // The free RAM in this hypervisor(in MB). 294 FreeRamMB int `json:"free_ram_mb"` 295 296 // The disk in this hypervisor(in GB). 297 LocalGB int `json:"local_gb"` 298 299 // The disk used in this hypervisor(in GB). 300 LocalGBUsed int `json:"local_gb_used"` 301 302 // The memory of this hypervisor(in MB). 303 MemoryMB int `json:"memory_mb"` 304 305 // The memory used in this hypervisor(in MB). 306 MemoryMBUsed int `json:"memory_mb_used"` 307 308 // The total number of running vms on all hypervisors. 309 RunningVMs int `json:"running_vms"` 310 311 // The number of vcpu in this hypervisor. 312 VCPUs int `json:"vcpus"` 313 314 // The number of vcpu used in this hypervisor. 315 VCPUsUsed int `json:"vcpus_used"` 316 } 317 318 type StatisticsResult struct { 319 gophercloud.Result 320 } 321 322 // Extract interprets any StatisticsResult as a Statistics, if possible. 323 func (r StatisticsResult) Extract() (*Statistics, error) { 324 var s struct { 325 Stats Statistics `json:"hypervisor_statistics"` 326 } 327 err := r.ExtractInto(&s) 328 return &s.Stats, err 329 } 330 331 // Uptime represents uptime and additional info for a specific hypervisor. 332 type Uptime struct { 333 // The hypervisor host name provided by the Nova virt driver. 334 // For the Ironic driver, it is the Ironic node uuid. 335 HypervisorHostname string `json:"hypervisor_hostname"` 336 337 // The id of the hypervisor. 338 ID string `json:"-"` 339 340 // The state of the hypervisor. One of up or down. 341 State string `json:"state"` 342 343 // The status of the hypervisor. One of enabled or disabled. 344 Status string `json:"status"` 345 346 // The total uptime of the hypervisor and information about average load. 347 Uptime string `json:"uptime"` 348 } 349 350 func (r *Uptime) UnmarshalJSON(b []byte) error { 351 type tmp Uptime 352 var s struct { 353 tmp 354 ID any `json:"id"` 355 } 356 357 err := json.Unmarshal(b, &s) 358 if err != nil { 359 return err 360 } 361 362 *r = Uptime(s.tmp) 363 364 // OpenStack Compute service returns ID in string representation since 365 // 2.53 microversion API (Pike release). 366 switch t := s.ID.(type) { 367 case int: 368 r.ID = strconv.Itoa(t) 369 case float64: 370 r.ID = strconv.Itoa(int(t)) 371 case string: 372 r.ID = t 373 default: 374 return fmt.Errorf("ID has unexpected type: %T", t) 375 } 376 377 return nil 378 } 379 380 type UptimeResult struct { 381 gophercloud.Result 382 } 383 384 // Extract interprets any UptimeResult as a Uptime, if possible. 385 func (r UptimeResult) Extract() (*Uptime, error) { 386 var s struct { 387 Uptime Uptime `json:"hypervisor"` 388 } 389 err := r.ExtractInto(&s) 390 return &s.Uptime, err 391 }