blob: 0dc47ecb2074d0ac97bc0b30e57e6444f79ecd28 [file] [log] [blame]
Ildar Svetlov8edb1e82018-03-27 17:32:09 +04001package schedulerstats
2
3import (
4 "encoding/json"
Ildar Svetlov16b85912018-11-19 13:04:55 +04005 "fmt"
Ildar Svetlov8edb1e82018-03-27 17:32:09 +04006 "math"
Ildar Svetlov16b85912018-11-19 13:04:55 +04007 "strconv"
Ildar Svetlov8edb1e82018-03-27 17:32:09 +04008
9 "gerrit.mcp.mirantis.net/debian/gophercloud.git/pagination"
10)
11
12// Capabilities represents the information of an individual StoragePool.
13type Capabilities struct {
14 // The following fields should be present in all storage drivers.
15 DriverVersion string `json:"driver_version"`
16 FreeCapacityGB float64 `json:"-"`
17 StorageProtocol string `json:"storage_protocol"`
18 TotalCapacityGB float64 `json:"-"`
19 VendorName string `json:"vendor_name"`
20 VolumeBackendName string `json:"volume_backend_name"`
21
22 // The following fields are optional and may have empty values depending
23 // on the storage driver in use.
24 ReservedPercentage int64 `json:"reserved_percentage"`
25 LocationInfo string `json:"location_info"`
26 QoSSupport bool `json:"QoS_support"`
27 ProvisionedCapacityGB float64 `json:"provisioned_capacity_gb"`
Ildar Svetlov16b85912018-11-19 13:04:55 +040028 MaxOverSubscriptionRatio string `json:"-"`
Ildar Svetlov8edb1e82018-03-27 17:32:09 +040029 ThinProvisioningSupport bool `json:"thin_provisioning_support"`
30 ThickProvisioningSupport bool `json:"thick_provisioning_support"`
31 TotalVolumes int64 `json:"total_volumes"`
32 FilterFunction string `json:"filter_function"`
33 GoodnessFuction string `json:"goodness_function"`
34 Mutliattach bool `json:"multiattach"`
35 SparseCopyVolume bool `json:"sparse_copy_volume"`
36}
37
38// StoragePool represents an individual StoragePool retrieved from the
39// schedulerstats API.
40type StoragePool struct {
41 Name string `json:"name"`
42 Capabilities Capabilities `json:"capabilities"`
43}
44
45func (r *Capabilities) UnmarshalJSON(b []byte) error {
46 type tmp Capabilities
47 var s struct {
48 tmp
Ildar Svetlov16b85912018-11-19 13:04:55 +040049 FreeCapacityGB interface{} `json:"free_capacity_gb"`
50 TotalCapacityGB interface{} `json:"total_capacity_gb"`
51 MaxOverSubscriptionRatio interface{} `json:"max_over_subscription_ratio"`
Ildar Svetlov8edb1e82018-03-27 17:32:09 +040052 }
53 err := json.Unmarshal(b, &s)
54 if err != nil {
55 return err
56 }
57 *r = Capabilities(s.tmp)
58
59 // Generic function to parse a capacity value which may be a numeric
60 // value, "unknown", or "infinite"
61 parseCapacity := func(capacity interface{}) float64 {
62 if capacity != nil {
Ildar Svetlov9a4174a2018-11-19 15:41:20 +040063 switch t := capacity.(type) {
Ildar Svetlov8edb1e82018-03-27 17:32:09 +040064 case float64:
Ildar Svetlov9a4174a2018-11-19 15:41:20 +040065 return t
Ildar Svetlov8edb1e82018-03-27 17:32:09 +040066 case string:
Ildar Svetlov9a4174a2018-11-19 15:41:20 +040067 switch t {
68 case "infinite":
Ildar Svetlov8edb1e82018-03-27 17:32:09 +040069 return math.Inf(1)
Ildar Svetlov9a4174a2018-11-19 15:41:20 +040070 default:
71 c, err := strconv.ParseFloat(t, 64)
72 if err != nil {
73 return 0.0
74 }
75 return c
Ildar Svetlov8edb1e82018-03-27 17:32:09 +040076 }
77 }
78 }
79 return 0.0
80 }
81
82 r.FreeCapacityGB = parseCapacity(s.FreeCapacityGB)
83 r.TotalCapacityGB = parseCapacity(s.TotalCapacityGB)
84
Ildar Svetlov16b85912018-11-19 13:04:55 +040085 switch t := s.MaxOverSubscriptionRatio.(type) {
86 case string:
87 r.MaxOverSubscriptionRatio = t
88 case float64:
89 r.MaxOverSubscriptionRatio = strconv.FormatFloat(t, 'f', -1, 64)
Ildar Svetlov12a49c62019-12-02 13:13:19 +040090 case nil:
91 r.MaxOverSubscriptionRatio = ""
Ildar Svetlov16b85912018-11-19 13:04:55 +040092 default:
93 return fmt.Errorf("MaxOverSubscriptionRatio has unexpected type: %T", t)
94 }
95
Ildar Svetlov8edb1e82018-03-27 17:32:09 +040096 return nil
97}
98
99// StoragePoolPage is a single page of all List results.
100type StoragePoolPage struct {
101 pagination.SinglePageBase
102}
103
104// IsEmpty satisfies the IsEmpty method of the Page interface. It returns true
105// if a List contains no results.
106func (page StoragePoolPage) IsEmpty() (bool, error) {
107 va, err := ExtractStoragePools(page)
108 return len(va) == 0, err
109}
110
111// ExtractStoragePools takes a List result and extracts the collection of
112// StoragePools returned by the API.
113func ExtractStoragePools(p pagination.Page) ([]StoragePool, error) {
114 var s struct {
115 StoragePools []StoragePool `json:"pools"`
116 }
117 err := (p.(StoragePoolPage)).ExtractInto(&s)
118 return s.StoragePools, err
119}