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  }