Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2013 Canonical Ltd. | 1 // Copyright 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package constraints | 4 package constraints |
5 | 5 |
6 import ( | 6 import ( |
7 "fmt" | 7 "fmt" |
8 "math" | 8 "math" |
9 "strconv" | 9 "strconv" |
10 "strings" | 10 "strings" |
(...skipping 20 matching lines...) Expand all Loading... | |
31 | 31 |
32 // CpuPower, if not nil, indicates that a machine must have at least tha t | 32 // CpuPower, if not nil, indicates that a machine must have at least tha t |
33 // amount of CPU power available, where 100 CpuPower is considered to be | 33 // amount of CPU power available, where 100 CpuPower is considered to be |
34 // equivalent to 1 Amazon ECU (or, roughly, a single 2007-era Xeon). | 34 // equivalent to 1 Amazon ECU (or, roughly, a single 2007-era Xeon). |
35 CpuPower *uint64 `json:"cpu-power,omitempty" yaml:"cpu-power,omitempty"` | 35 CpuPower *uint64 `json:"cpu-power,omitempty" yaml:"cpu-power,omitempty"` |
36 | 36 |
37 // Mem, if not nil, indicates that a machine must have at least that man y | 37 // Mem, if not nil, indicates that a machine must have at least that man y |
38 // megabytes of RAM. | 38 // megabytes of RAM. |
39 Mem *uint64 `json:"mem,omitempty" yaml:"mem,omitempty"` | 39 Mem *uint64 `json:"mem,omitempty" yaml:"mem,omitempty"` |
40 | 40 |
41 » // OsDisk, if not nil, indicates that a machine must have at least that | 41 » // RootDisk, if not nil, indicates that a machine must have at least |
42 » // amount of disk space available in the OS disk, aka root | 42 » // that many megabytes of disk space available in the root disk. In |
43 » // partition. In providers where the OS disk is configurable at | 43 » // providers where the root disk is configurable at instance startup |
44 » // instance startup time, an instance with the specified amount of disk | 44 » // time, an instance with the specified amount of disk space in the OS |
45 » // space in the OS disk will be requested. | 45 » // disk might be requested. |
46 » OsDisk *uint64 `json:"os-disk,omitempty" yaml:"os-disk,omitempty"` | 46 » RootDisk *uint64 `json:"root-disk,omitempty" yaml:"root-disk,omitempty"` |
fwereade
2013/08/13 17:27:00
I'm not sure about the name. InstanceDisk, or Loca
sidnei.da.silva
2013/08/13 18:00:56
As explained in the bug comments, this constraint
| |
47 } | 47 } |
48 | 48 |
49 // String expresses a constraints.Value in the language in which it was specifie d. | 49 // String expresses a constraints.Value in the language in which it was specifie d. |
50 func (v Value) String() string { | 50 func (v Value) String() string { |
51 var strs []string | 51 var strs []string |
52 if v.Arch != nil { | 52 if v.Arch != nil { |
53 strs = append(strs, "arch="+*v.Arch) | 53 strs = append(strs, "arch="+*v.Arch) |
54 } | 54 } |
55 if v.Container != nil { | 55 if v.Container != nil { |
56 strs = append(strs, "container="+string(*v.Container)) | 56 strs = append(strs, "container="+string(*v.Container)) |
57 } | 57 } |
58 if v.CpuCores != nil { | 58 if v.CpuCores != nil { |
59 strs = append(strs, "cpu-cores="+uintStr(*v.CpuCores)) | 59 strs = append(strs, "cpu-cores="+uintStr(*v.CpuCores)) |
60 } | 60 } |
61 if v.CpuPower != nil { | 61 if v.CpuPower != nil { |
62 strs = append(strs, "cpu-power="+uintStr(*v.CpuPower)) | 62 strs = append(strs, "cpu-power="+uintStr(*v.CpuPower)) |
63 } | 63 } |
64 if v.Mem != nil { | 64 if v.Mem != nil { |
65 s := uintStr(*v.Mem) | 65 s := uintStr(*v.Mem) |
66 if s != "" { | 66 if s != "" { |
67 s += "M" | 67 s += "M" |
68 } | 68 } |
69 strs = append(strs, "mem="+s) | 69 strs = append(strs, "mem="+s) |
70 } | 70 } |
71 » if v.OsDisk != nil { | 71 » if v.RootDisk != nil { |
72 » » s := uintStr(*v.OsDisk) | 72 » » s := uintStr(*v.RootDisk) |
73 if s != "" { | 73 if s != "" { |
74 s += "M" | 74 s += "M" |
75 } | 75 } |
76 » » strs = append(strs, "os-disk="+s) | 76 » » strs = append(strs, "root-disk="+s) |
77 } | 77 } |
78 return strings.Join(strs, " ") | 78 return strings.Join(strs, " ") |
79 } | 79 } |
80 | 80 |
81 // WithFallbacks returns a copy of v with nil values taken from v0. | 81 // WithFallbacks returns a copy of v with nil values taken from v0. |
82 func (v Value) WithFallbacks(v0 Value) Value { | 82 func (v Value) WithFallbacks(v0 Value) Value { |
83 v1 := v0 | 83 v1 := v0 |
84 if v.Arch != nil { | 84 if v.Arch != nil { |
85 v1.Arch = v.Arch | 85 v1.Arch = v.Arch |
86 } | 86 } |
87 if v.Container != nil { | 87 if v.Container != nil { |
88 v1.Container = v.Container | 88 v1.Container = v.Container |
89 } | 89 } |
90 if v.CpuCores != nil { | 90 if v.CpuCores != nil { |
91 v1.CpuCores = v.CpuCores | 91 v1.CpuCores = v.CpuCores |
92 } | 92 } |
93 if v.CpuPower != nil { | 93 if v.CpuPower != nil { |
94 v1.CpuPower = v.CpuPower | 94 v1.CpuPower = v.CpuPower |
95 } | 95 } |
96 if v.Mem != nil { | 96 if v.Mem != nil { |
97 v1.Mem = v.Mem | 97 v1.Mem = v.Mem |
98 } | 98 } |
99 » if v.OsDisk != nil { | 99 » if v.RootDisk != nil { |
100 » » v1.OsDisk = v.OsDisk | 100 » » v1.RootDisk = v.RootDisk |
101 } | 101 } |
102 return v1 | 102 return v1 |
103 } | 103 } |
104 | 104 |
105 func uintStr(i uint64) string { | 105 func uintStr(i uint64) string { |
106 if i == 0 { | 106 if i == 0 { |
107 return "" | 107 return "" |
108 } | 108 } |
109 return fmt.Sprintf("%d", i) | 109 return fmt.Sprintf("%d", i) |
110 } | 110 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 case "arch": | 168 case "arch": |
169 err = v.setArch(str) | 169 err = v.setArch(str) |
170 case "container": | 170 case "container": |
171 err = v.setContainer(str) | 171 err = v.setContainer(str) |
172 case "cpu-cores": | 172 case "cpu-cores": |
173 err = v.setCpuCores(str) | 173 err = v.setCpuCores(str) |
174 case "cpu-power": | 174 case "cpu-power": |
175 err = v.setCpuPower(str) | 175 err = v.setCpuPower(str) |
176 case "mem": | 176 case "mem": |
177 err = v.setMem(str) | 177 err = v.setMem(str) |
178 » case "os-disk": | 178 » case "root-disk": |
179 » » err = v.setOsDisk(str) | 179 » » err = v.setRootDisk(str) |
180 default: | 180 default: |
181 return fmt.Errorf("unknown constraint %q", name) | 181 return fmt.Errorf("unknown constraint %q", name) |
182 } | 182 } |
183 if err != nil { | 183 if err != nil { |
184 return fmt.Errorf("bad %q constraint: %v", name, err) | 184 return fmt.Errorf("bad %q constraint: %v", name, err) |
185 } | 185 } |
186 return nil | 186 return nil |
187 } | 187 } |
188 | 188 |
189 // SetYAML is required to unmarshall a constraints.Value object | 189 // SetYAML is required to unmarshall a constraints.Value object |
(...skipping 11 matching lines...) Expand all Loading... | |
201 v.Arch = &vstr | 201 v.Arch = &vstr |
202 case "container": | 202 case "container": |
203 ctype := instance.ContainerType(vstr) | 203 ctype := instance.ContainerType(vstr) |
204 v.Container = &ctype | 204 v.Container = &ctype |
205 case "cpu-cores": | 205 case "cpu-cores": |
206 v.CpuCores, err = parseUint64(vstr) | 206 v.CpuCores, err = parseUint64(vstr) |
207 case "cpu-power": | 207 case "cpu-power": |
208 v.CpuPower, err = parseUint64(vstr) | 208 v.CpuPower, err = parseUint64(vstr) |
209 case "mem": | 209 case "mem": |
210 v.Mem, err = parseUint64(vstr) | 210 v.Mem, err = parseUint64(vstr) |
211 » » case "os-disk": | 211 » » case "root-disk": |
212 » » » v.OsDisk, err = parseUint64(vstr) | 212 » » » v.RootDisk, err = parseUint64(vstr) |
213 default: | 213 default: |
214 return false | 214 return false |
215 } | 215 } |
216 if err != nil { | 216 if err != nil { |
217 return false | 217 return false |
218 } | 218 } |
219 } | 219 } |
220 return true | 220 return true |
221 } | 221 } |
222 | 222 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 } | 265 } |
266 | 266 |
267 func (v *Value) setCpuPower(str string) (err error) { | 267 func (v *Value) setCpuPower(str string) (err error) { |
268 if v.CpuPower != nil { | 268 if v.CpuPower != nil { |
269 return fmt.Errorf("already set") | 269 return fmt.Errorf("already set") |
270 } | 270 } |
271 v.CpuPower, err = parseUint64(str) | 271 v.CpuPower, err = parseUint64(str) |
272 return | 272 return |
273 } | 273 } |
274 | 274 |
275 func (v *Value) setMem(str string) error { | 275 func (v *Value) setMem(str string) (err error) { |
276 if v.Mem != nil { | 276 if v.Mem != nil { |
277 return fmt.Errorf("already set") | 277 return fmt.Errorf("already set") |
278 } | 278 } |
279 » var value uint64 | 279 » v.Mem, err = parseSize(str) |
280 » if str != "" { | 280 » return |
281 » » mult := 1.0 | 281 } |
282 » » if m, ok := mbSuffixes[str[len(str)-1:]]; ok { | 282 |
283 » » » str = str[:len(str)-1] | 283 func (v *Value) setRootDisk(str string) (err error) { |
284 » » » mult = m | 284 » if v.RootDisk != nil { |
285 » » } | 285 » » return fmt.Errorf("already set") |
286 » » val, err := strconv.ParseFloat(str, 64) | 286 » } |
287 » » if err != nil || val < 0 { | 287 » v.RootDisk, err = parseSize(str) |
288 » » » return fmt.Errorf("must be a non-negative float with opt ional M/G/T/P suffix") | 288 » return |
289 » » } | |
290 » » val *= mult | |
291 » » value = uint64(math.Ceil(val)) | |
292 » } | |
293 » v.Mem = &value | |
294 » return nil | |
295 } | |
296 | |
297 func (v *Value) setOsDisk(str string) error { | |
298 » if v.OsDisk != nil { | |
299 » » return fmt.Errorf("already set") | |
300 » } | |
301 » var value uint64 | |
302 » if str != "" { | |
303 » » mult := 1.0 | |
304 » » if m, ok := mbSuffixes[str[len(str)-1:]]; ok { | |
305 » » » str = str[:len(str)-1] | |
306 » » » mult = m | |
307 » » } | |
308 » » val, err := strconv.ParseFloat(str, 64) | |
309 » » if err != nil || val < 0 { | |
310 » » » return fmt.Errorf("must be a non-negative float with opt ional M/G/T/P suffix") | |
311 » » } | |
312 » » val *= mult | |
313 » » value = uint64(math.Ceil(val)) | |
314 » } | |
fwereade
2013/08/13 17:27:00
Please pull this block out into a common function,
sidnei.da.silva
2013/08/13 18:00:56
Done.
| |
315 » v.OsDisk = &value | |
316 » return nil | |
317 } | 289 } |
318 | 290 |
319 func parseUint64(str string) (*uint64, error) { | 291 func parseUint64(str string) (*uint64, error) { |
320 var value uint64 | 292 var value uint64 |
321 if str != "" { | 293 if str != "" { |
322 if val, err := strconv.ParseUint(str, 10, 64); err != nil { | 294 if val, err := strconv.ParseUint(str, 10, 64); err != nil { |
323 return nil, fmt.Errorf("must be a non-negative integer") | 295 return nil, fmt.Errorf("must be a non-negative integer") |
324 } else { | 296 } else { |
325 value = uint64(val) | 297 value = uint64(val) |
326 } | 298 } |
327 } | 299 } |
328 return &value, nil | 300 return &value, nil |
329 } | 301 } |
330 | 302 |
303 func parseSize(str string) (*uint64, error) { | |
304 var value uint64 | |
305 if str != "" { | |
306 mult := 1.0 | |
307 if m, ok := mbSuffixes[str[len(str)-1:]]; ok { | |
308 str = str[:len(str)-1] | |
309 mult = m | |
310 } | |
311 val, err := strconv.ParseFloat(str, 64) | |
312 if err != nil || val < 0 { | |
313 return nil, fmt.Errorf("must be a non-negative float wit h optional M/G/T/P suffix") | |
314 } | |
315 val *= mult | |
316 value = uint64(math.Ceil(val)) | |
317 } | |
318 return &value, nil | |
319 } | |
320 | |
331 var mbSuffixes = map[string]float64{ | 321 var mbSuffixes = map[string]float64{ |
332 "M": 1, | 322 "M": 1, |
333 "G": 1024, | 323 "G": 1024, |
334 "T": 1024 * 1024, | 324 "T": 1024 * 1024, |
335 "P": 1024 * 1024 * 1024, | 325 "P": 1024 * 1024 * 1024, |
336 } | 326 } |
LEFT | RIGHT |