github.com/openshift/installer@v1.4.17/pkg/quota/quota.go (about) 1 package quota 2 3 import ( 4 "errors" 5 "fmt" 6 "math" 7 "strings" 8 ) 9 10 // Quota stores the used and limit for a resouce's quota. 11 type Quota struct { 12 Service string 13 Name string 14 Region string 15 16 InUse int64 17 Limit int64 18 19 Unlimited bool 20 } 21 22 // Constraint defines a check against availablity 23 // for a resource quota. 24 type Constraint struct { 25 Name string 26 // This should be global or specific region. 27 Region string 28 // Count is the number of the resource that is required 29 // to be free for use. 30 Count int64 31 } 32 33 // ConstraintReportResult provide one word result for the constraint 34 type ConstraintReportResult string 35 36 const ( 37 // Available corresponds to a constraint that is available. 38 Available ConstraintReportResult = "Available" 39 // AvailableButLow corresponds to a constraint that is available but there is very low overhead after satisfying the constraint. 40 AvailableButLow ConstraintReportResult = "AvailableButLow" 41 // NotAvailable corresponds to a constraint that is not available. 42 NotAvailable ConstraintReportResult = "NotAvailable" 43 // Unknown corresponds to a constraint that could not be calculated. 44 Unknown ConstraintReportResult = "Unknown" 45 ) 46 47 // ConstraintReport provides result for a given constraint. 48 type ConstraintReport struct { 49 For *Constraint 50 Result ConstraintReportResult 51 Message string 52 } 53 54 // Check returns whether the checks constraints are possible gives the quotas. 55 // It returns an erros when any one of the constraint's result was `NotAvailable` or `Unknown` 56 func Check(quotas []Quota, checks []Constraint) ([]ConstraintReport, error) { 57 reports := make([]ConstraintReport, 0, len(checks)) 58 59 match := func(check Constraint) (Quota, bool) { 60 for _, q := range quotas { 61 if !strings.EqualFold(check.Name, q.Name) { 62 continue 63 } 64 if !strings.EqualFold(q.Region, check.Region) { 65 continue 66 } 67 return q, true 68 } 69 return Quota{}, false 70 } 71 72 for idx, check := range checks { 73 report := ConstraintReport{ 74 For: &checks[idx], 75 } 76 matched, ok := match(check) 77 if !ok { 78 report.Result = Unknown 79 report.Message = "No matching quota found for the constraint" 80 reports = append(reports, report) 81 continue 82 } 83 84 if matched.Unlimited { 85 report.Result = Available 86 report.Message = "Unlimited quota found for the constraint" 87 reports = append(reports, report) 88 continue 89 } 90 91 if check.Count > matched.Limit { 92 report.Result = NotAvailable 93 report.Message = fmt.Sprintf("the required number of resources (%d) is more than the limit of %d", check.Count, matched.Limit) 94 reports = append(reports, report) 95 continue 96 } 97 98 avail := matched.Limit - matched.InUse 99 availAfterUse := avail - check.Count 100 headroom := int64(math.Ceil(0.2 * float64(matched.Limit))) 101 if check.Count > avail { 102 report.Result = NotAvailable 103 report.Message = fmt.Sprintf("the required number of resources (%d) is more than remaining quota of %d", check.Count, avail) 104 reports = append(reports, report) 105 continue 106 } 107 if availAfterUse <= headroom { 108 report.Result = AvailableButLow 109 report.Message = fmt.Sprintf("the required number of resources is available but only %d will be leftover", availAfterUse) 110 reports = append(reports, report) 111 continue 112 } 113 report.Result = Available 114 report.Message = "the required number of resources is available" 115 reports = append(reports, report) 116 } 117 118 failed := 0 119 for _, r := range reports { 120 if r.Result == Unknown || 121 r.Result == NotAvailable { 122 failed++ 123 } 124 } 125 if failed > 0 { 126 return reports, errors.New("%d checks failed") 127 } 128 129 return reports, nil 130 }