|
| 1 | +package cloudian |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "encoding/json" |
| 6 | + "fmt" |
| 7 | + "strconv" |
| 8 | +) |
| 9 | + |
| 10 | +// QualityOfService configures data limits for a Group or User. |
| 11 | +type QualityOfService struct { |
| 12 | + // Warning is the soft limit that triggers a warning. |
| 13 | + Warning QualityOfServiceLimits |
| 14 | + // Hard is the hard limit. |
| 15 | + Hard QualityOfServiceLimits |
| 16 | +} |
| 17 | + |
| 18 | +// QualityOfService configures data limits. |
| 19 | +type QualityOfServiceLimits struct { |
| 20 | + // StorageQuotaKiBs is the limit for total stored data in KiB. |
| 21 | + StorageQuotaKiBs *int64 |
| 22 | + // StorageQuotaCount is the limit for total number of objects. |
| 23 | + StorageQuotaCount *int64 |
| 24 | + // RequestsPerMin is the limit for number of HTTP requests per minute. |
| 25 | + RequestsPerMin *int64 |
| 26 | + // InboundKiBsPerMin is the limit for inbound data per minute in KiB. |
| 27 | + InboundKiBsPerMin *int64 |
| 28 | + // OutboundKiBsPerMin is the limit for outbound data per minute in KiB. |
| 29 | + OutboundKiBsPerMin *int64 |
| 30 | +} |
| 31 | + |
| 32 | +// nolint: gocyclo |
| 33 | +func (qos *QualityOfService) unmarshalQOSList(raw []byte) error { |
| 34 | + var data struct { |
| 35 | + QOSLimitList []struct { |
| 36 | + Type string `json:"type"` |
| 37 | + Value int64 `json:"value"` |
| 38 | + } `json:"qosLimitList"` |
| 39 | + } |
| 40 | + |
| 41 | + if err := json.Unmarshal(raw, &data); err != nil { |
| 42 | + return err |
| 43 | + } |
| 44 | + |
| 45 | + for _, item := range data.QOSLimitList { |
| 46 | + v := &item.Value |
| 47 | + switch item.Type { |
| 48 | + case "STORAGE_QUOTA_KBYTES_LH": |
| 49 | + qos.Hard.StorageQuotaKiBs = v |
| 50 | + case "STORAGE_QUOTA_KBYTES_LW": |
| 51 | + qos.Warning.StorageQuotaKiBs = v |
| 52 | + case "STORAGE_QUOTA_COUNT_LH": |
| 53 | + qos.Hard.StorageQuotaCount = v |
| 54 | + case "STORAGE_QUOTA_COUNT_LW": |
| 55 | + qos.Warning.StorageQuotaCount = v |
| 56 | + case "REQUEST_RATE_LH": |
| 57 | + qos.Hard.RequestsPerMin = v |
| 58 | + case "REQUEST_RATE_LW": |
| 59 | + qos.Warning.RequestsPerMin = v |
| 60 | + case "DATAKBYTES_IN_LH": |
| 61 | + qos.Hard.InboundKiBsPerMin = v |
| 62 | + case "DATAKBYTES_IN_LW": |
| 63 | + qos.Warning.InboundKiBsPerMin = v |
| 64 | + case "DATAKBYTES_OUT_LH": |
| 65 | + qos.Hard.OutboundKiBsPerMin = v |
| 66 | + case "DATAKBYTES_OUT_LW": |
| 67 | + qos.Warning.OutboundKiBsPerMin = v |
| 68 | + } |
| 69 | + } |
| 70 | + return nil |
| 71 | +} |
| 72 | + |
| 73 | +func (qos *QualityOfService) queryParams(params map[string]string) error { |
| 74 | + rawParams := map[string]*int64{ |
| 75 | + "hlStorageQuotaKBytes": qos.Hard.StorageQuotaKiBs, |
| 76 | + "wlStorageQuotaKBytes": qos.Warning.StorageQuotaKiBs, |
| 77 | + "hlStorageQuotaCount": qos.Hard.StorageQuotaCount, |
| 78 | + "wlStorageQuotaCount": qos.Warning.StorageQuotaCount, |
| 79 | + "hlRequestRate": qos.Hard.RequestsPerMin, |
| 80 | + "wlRequestRate": qos.Warning.RequestsPerMin, |
| 81 | + "hlDataKBytesIn": qos.Hard.InboundKiBsPerMin, |
| 82 | + "wlDataKBytesIn": qos.Warning.InboundKiBsPerMin, |
| 83 | + "hlDataKBytesOut": qos.Hard.OutboundKiBsPerMin, |
| 84 | + "wlDataKBytesOut": qos.Warning.OutboundKiBsPerMin, |
| 85 | + } |
| 86 | + |
| 87 | + for key, raw := range rawParams { |
| 88 | + val := int64(-1) |
| 89 | + if raw != nil { |
| 90 | + val = *raw |
| 91 | + } |
| 92 | + if val < -1 { |
| 93 | + return fmt.Errorf("invalid QoS limit value: %d", val) |
| 94 | + } |
| 95 | + params[key] = strconv.FormatInt(val, 10) |
| 96 | + } |
| 97 | + return nil |
| 98 | +} |
| 99 | + |
| 100 | +// SetQOS sets QualityOfService limits for a Group or User, depending on the value of GroupID and UserID. |
| 101 | +// |
| 102 | +// User-level QoS for a specific user (GroupID="<groupId>", UserID="<userId>") |
| 103 | +// Default user-level QoS for a specific group (GroupID="<groupId>", UserID="ALL") |
| 104 | +// Default user-level QoS for the whole region (GroupID="*", UserID="ALL") |
| 105 | +// Group-level QoS for a specific group (GroupID="<groupId>", UserID="*") |
| 106 | +// Default group-level QoS for the whole region (GroupID="ALL", UserID="*") |
| 107 | +func (client Client) SetQOS(ctx context.Context, user User, qos QualityOfService) error { |
| 108 | + params := make(map[string]string) |
| 109 | + if err := qos.queryParams(params); err != nil { |
| 110 | + return err |
| 111 | + } |
| 112 | + |
| 113 | + resp, err := client.newRequest(ctx). |
| 114 | + SetQueryParam("userId", user.UserID). |
| 115 | + SetQueryParam("groupId", user.GroupID). |
| 116 | + SetQueryParams(params). |
| 117 | + Post("/qos/limits") |
| 118 | + if err != nil { |
| 119 | + return err |
| 120 | + } |
| 121 | + |
| 122 | + switch resp.StatusCode() { |
| 123 | + case 200: |
| 124 | + return nil |
| 125 | + default: |
| 126 | + return fmt.Errorf("POST quota unexpected status: %d", resp.StatusCode()) |
| 127 | + } |
| 128 | +} |
| 129 | + |
| 130 | +// SetQOS gets QualityOfService limits for a Group or User, depending on the value of GroupID and UserID. |
| 131 | +// See SetQOS for details. |
| 132 | +func (client Client) GetQOS(ctx context.Context, user User) (*QualityOfService, error) { |
| 133 | + resp, err := client.newRequest(ctx). |
| 134 | + SetQueryParam("userId", user.UserID). |
| 135 | + SetQueryParam("groupId", user.GroupID). |
| 136 | + Get("/qos/limits") |
| 137 | + if err != nil { |
| 138 | + return nil, err |
| 139 | + } |
| 140 | + |
| 141 | + switch resp.StatusCode() { |
| 142 | + case 200: |
| 143 | + qos := &QualityOfService{} |
| 144 | + return qos, qos.unmarshalQOSList(resp.Body()) |
| 145 | + default: |
| 146 | + return nil, fmt.Errorf("GET quota unexpected status: %d", resp.StatusCode()) |
| 147 | + } |
| 148 | +} |
0 commit comments