@@ -28,14 +28,15 @@ import (
2828 "github.com/deckhouse/virtualization/api/core/v1alpha2"
2929)
3030
31+ var ErrSizingPolicyValidation = errors .New ("please check the sizing policy of the virtual machine class or contact the administrator for more information" )
32+
3133type SizePolicyService struct {}
3234
3335func NewSizePolicyService () * SizePolicyService {
3436 return & SizePolicyService {}
3537}
3638
3739func (s * SizePolicyService ) CheckVMMatchedSizePolicy (vm * v1alpha2.VirtualMachine , vmClass * v1alpha2.VirtualMachineClass ) error {
38- // check if no sizing policy requirements are set
3940 if vmClass == nil || len (vmClass .Spec .SizingPolicies ) == 0 {
4041 return nil
4142 }
@@ -45,14 +46,25 @@ func (s *SizePolicyService) CheckVMMatchedSizePolicy(vm *v1alpha2.VirtualMachine
4546 return NewNoSizingPolicyMatchError (vm .Name , vm .Spec .VirtualMachineClassName )
4647 }
4748
48- var errorsArray []error
49+ var errs []error
4950
50- errorsArray = append (errorsArray , validateCoreFraction (vm , sizePolicy )... )
51- errorsArray = append (errorsArray , validateMemory (vm , sizePolicy )... )
52- errorsArray = append (errorsArray , validatePerCoreMemory (vm , sizePolicy )... )
51+ err := validateCoreFraction (vm , sizePolicy )
52+ if err != nil {
53+ errs = append (errs , err )
54+ }
5355
54- if len (errorsArray ) > 0 {
55- return fmt .Errorf ("sizing policy validate: %w" , errors .Join (errorsArray ... ))
56+ err = validateMemory (vm , sizePolicy )
57+ if err != nil {
58+ errs = append (errs , err )
59+ }
60+
61+ err = validatePerCoreMemory (vm , sizePolicy )
62+ if err != nil {
63+ errs = append (errs , err )
64+ }
65+
66+ if len (errs ) > 0 {
67+ return fmt .Errorf ("sizing policy validation has failed: %w: %w" , errors .Join (errs ... ), ErrSizingPolicyValidation )
5668 }
5769
5870 return nil
@@ -72,16 +84,15 @@ func getVMSizePolicy(vm *v1alpha2.VirtualMachine, vmClass *v1alpha2.VirtualMachi
7284 return nil
7385}
7486
75- func validateCoreFraction (vm * v1alpha2.VirtualMachine , sp * v1alpha2.SizingPolicy ) ( errorsArray [] error ) {
87+ func validateCoreFraction (vm * v1alpha2.VirtualMachine , sp * v1alpha2.SizingPolicy ) error {
7688 if len (sp .CoreFractions ) == 0 {
77- return
89+ return nil
7890 }
7991
80- fractionStr := strings .ReplaceAll (vm .Spec .CPU .CoreFraction , "%" , " " )
92+ fractionStr , _ := strings .CutSuffix (vm .Spec .CPU .CoreFraction , "%" )
8193 fraction , err := strconv .Atoi (fractionStr )
8294 if err != nil {
83- errorsArray = append (errorsArray , fmt .Errorf ("unable to parse CPU core fraction: %w" , err ))
84- return
95+ return fmt .Errorf ("unable to parse CPU core fraction: %w" , err )
8596 }
8697
8798 hasFractionValueInPolicy := false
@@ -92,33 +103,34 @@ func validateCoreFraction(vm *v1alpha2.VirtualMachine, sp *v1alpha2.SizingPolicy
92103 }
93104
94105 if ! hasFractionValueInPolicy {
95- errorsArray = append (errorsArray , fmt .Errorf ("VM core fraction value %d is not within the allowed values" , fraction ))
106+ formattedCoreFractions := formatCoreFractionValues (sp .CoreFractions )
107+ return fmt .Errorf ("VM core fraction value %s is not within the allowed values: %v" , vm .Spec .CPU .CoreFraction , formattedCoreFractions )
96108 }
97109
98- return
110+ return nil
99111}
100112
101- func validateMemory (vm * v1alpha2.VirtualMachine , sp * v1alpha2.SizingPolicy ) ( errorsArray [] error ) {
113+ func validateMemory (vm * v1alpha2.VirtualMachine , sp * v1alpha2.SizingPolicy ) error {
102114 if sp .Memory == nil || sp .Memory .Max == nil || sp .Memory .Max .IsZero () {
103- return
115+ return nil
104116 }
105117
106118 if sp .Memory .Min != nil && vm .Spec .Memory .Size .Cmp (* sp .Memory .Min ) == common .CmpLesser {
107- errorsArray = append ( errorsArray , fmt .Errorf (
119+ return fmt .Errorf (
108120 "requested VM memory (%s) is less than the minimum allowed, available range [%s, %s]" ,
109121 vm .Spec .Memory .Size .String (),
110122 sp .Memory .Min .String (),
111123 sp .Memory .Max .String (),
112- ))
124+ )
113125 }
114126
115127 if vm .Spec .Memory .Size .Cmp (* sp .Memory .Max ) == common .CmpGreater {
116- errorsArray = append ( errorsArray , fmt .Errorf (
128+ return fmt .Errorf (
117129 "requested VM memory (%s) exceeds the maximum allowed, available range [%s, %s]" ,
118130 vm .Spec .Memory .Size .String (),
119131 sp .Memory .Min .String (),
120132 sp .Memory .Max .String (),
121- ))
133+ )
122134 }
123135
124136 if sp .Memory .Step != nil && ! sp .Memory .Step .IsZero () {
@@ -128,16 +140,16 @@ func validateMemory(vm *v1alpha2.VirtualMachine, sp *v1alpha2.SizingPolicy) (err
128140 }
129141 err := validateIsQuantized (vm .Spec .Memory .Size , minVal , * sp .Memory .Max , * sp .Memory .Step , "VM memory" )
130142 if err != nil {
131- errorsArray = append ( errorsArray , err )
143+ return err
132144 }
133145 }
134146
135- return
147+ return nil
136148}
137149
138- func validatePerCoreMemory (vm * v1alpha2.VirtualMachine , sp * v1alpha2.SizingPolicy ) ( errorsArray [] error ) {
150+ func validatePerCoreMemory (vm * v1alpha2.VirtualMachine , sp * v1alpha2.SizingPolicy ) error {
139151 if sp .Memory == nil || sp .Memory .PerCore == nil || sp .Memory .PerCore .Max == nil || sp .Memory .PerCore .Max .IsZero () {
140- return
152+ return nil
141153 }
142154
143155 // Calculate memory portion per CPU core
@@ -147,21 +159,21 @@ func validatePerCoreMemory(vm *v1alpha2.VirtualMachine, sp *v1alpha2.SizingPolic
147159 perCoreMemory := resource .NewQuantity (vmPerCore , resource .BinarySI )
148160
149161 if sp .Memory .PerCore .Min != nil && perCoreMemory .Cmp (* sp .Memory .PerCore .Min ) == common .CmpLesser {
150- errorsArray = append ( errorsArray , fmt .Errorf (
162+ return fmt .Errorf (
151163 "requested VM per core memory (%s) is less than the minimum allowed, available range [%s, %s]" ,
152164 perCoreMemory .String (),
153165 sp .Memory .PerCore .Min .String (),
154166 sp .Memory .PerCore .Max .String (),
155- ))
167+ )
156168 }
157169
158170 if perCoreMemory .Cmp (* sp .Memory .PerCore .Max ) == common .CmpGreater {
159- errorsArray = append ( errorsArray , fmt .Errorf (
171+ return fmt .Errorf (
160172 "requested VM per core memory (%s) exceeds the maximum allowed, available range [%s, %s]" ,
161173 perCoreMemory .String (),
162174 sp .Memory .PerCore .Min .String (),
163175 sp .Memory .PerCore .Max .String (),
164- ))
176+ )
165177 }
166178
167179 if sp .Memory .Step != nil && ! sp .Memory .Step .IsZero () {
@@ -171,11 +183,11 @@ func validatePerCoreMemory(vm *v1alpha2.VirtualMachine, sp *v1alpha2.SizingPolic
171183 }
172184 err := validateIsQuantized (* perCoreMemory , minVal , * sp .Memory .PerCore .Max , * sp .Memory .Step , "VM per core memory" )
173185 if err != nil {
174- errorsArray = append ( errorsArray , err )
186+ return err
175187 }
176188 }
177189
178- return
190+ return nil
179191}
180192
181193func validateIsQuantized (value , min , max , step resource.Quantity , source string ) (err error ) {
@@ -212,3 +224,11 @@ func generateValidGrid(min, max, step resource.Quantity) []resource.Quantity {
212224
213225 return grid
214226}
227+
228+ func formatCoreFractionValues (cf []v1alpha2.CoreFractionValue ) []string {
229+ result := make ([]string , len (cf ))
230+ for i , v := range cf {
231+ result [i ] = fmt .Sprintf ("%d%%" , v )
232+ }
233+ return result
234+ }
0 commit comments