-
Notifications
You must be signed in to change notification settings - Fork 141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add mems, cpus check and move common codes into utils #344
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package utils | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/syndtr/gocapability/capability" | ||
) | ||
|
||
// LastCap return last cap of system | ||
func LastCap() capability.Cap { | ||
last := capability.CAP_LAST_CAP | ||
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap | ||
if last == capability.Cap(63) { | ||
last = capability.CAP_BLOCK_SUSPEND | ||
} | ||
|
||
return last | ||
} | ||
|
||
// UnitListValid checks strings whether is valid for | ||
// cpuset.cpus and cpuset.mems, duplicates are allowed | ||
// Supported formats: | ||
// 1 | ||
// 0-3 | ||
// 0-2,1,3 | ||
// 0-2,1-3,4 | ||
func UnitListValid(val string) error { | ||
if val == "" { | ||
return nil | ||
} | ||
|
||
split := strings.Split(val, ",") | ||
errInvalidFormat := fmt.Errorf("invalid format: %s", val) | ||
|
||
for _, r := range split { | ||
if !strings.Contains(r, "-") { | ||
_, err := strconv.Atoi(r) | ||
if err != nil { | ||
return errInvalidFormat | ||
} | ||
} else { | ||
split := strings.SplitN(r, "-", 2) | ||
min, err := strconv.Atoi(split[0]) | ||
if err != nil { | ||
return errInvalidFormat | ||
} | ||
max, err := strconv.Atoi(split[1]) | ||
if err != nil { | ||
return errInvalidFormat | ||
} | ||
if max < min { | ||
return errInvalidFormat | ||
} | ||
} | ||
} | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ import ( | |
|
||
"github.com/blang/semver" | ||
rspec "github.com/opencontainers/runtime-spec/specs-go" | ||
"github.com/opencontainers/runtime-tools/utils" | ||
"github.com/sirupsen/logrus" | ||
"github.com/syndtr/gocapability/capability" | ||
) | ||
|
@@ -633,6 +634,20 @@ func (v *Validator) CheckLinuxResources() (msgs []string) { | |
logrus.Debugf("check linux resources") | ||
|
||
r := v.spec.Linux.Resources | ||
|
||
if r.CPU != nil { | ||
if r.CPU.Cpus != "" { | ||
if err := utils.UnitListValid(r.CPU.Cpus); err != nil { | ||
msgs = append(msgs, err.Error()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure this check (or your following |
||
} | ||
} | ||
if r.CPU.Mems != "" { | ||
if err := utils.UnitListValid(r.CPU.Mems); err != nil { | ||
msgs = append(msgs, err.Error()) | ||
} | ||
} | ||
} | ||
|
||
if r.Memory != nil { | ||
if r.Memory.Limit != nil && r.Memory.Swap != nil && uint64(*r.Memory.Limit) > uint64(*r.Memory.Swap) { | ||
msgs = append(msgs, fmt.Sprintf("Minimum memoryswap should be larger than memory limit")) | ||
|
@@ -641,6 +656,7 @@ func (v *Validator) CheckLinuxResources() (msgs []string) { | |
msgs = append(msgs, fmt.Sprintf("Minimum memory limit should be larger than memory reservation")) | ||
} | ||
} | ||
|
||
if r.Network != nil && v.HostSpecific { | ||
var exist bool | ||
interfaces, err := net.Interfaces() | ||
|
@@ -715,7 +731,7 @@ func CapValid(c string, hostSpecific bool) error { | |
} | ||
for _, cap := range capability.List() { | ||
if c == fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())) { | ||
if hostSpecific && cap > LastCap() { | ||
if hostSpecific && cap > utils.LastCap() { | ||
return fmt.Errorf("CAP_%s is not supported on the current host", c) | ||
} | ||
isValid = true | ||
|
@@ -729,17 +745,6 @@ func CapValid(c string, hostSpecific bool) error { | |
return nil | ||
} | ||
|
||
// LastCap return last cap of system | ||
func LastCap() capability.Cap { | ||
last := capability.CAP_LAST_CAP | ||
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap | ||
if last == capability.Cap(63) { | ||
last = capability.CAP_BLOCK_SUSPEND | ||
} | ||
|
||
return last | ||
} | ||
|
||
func envValid(env string) bool { | ||
items := strings.Split(env, "=") | ||
if len(items) < 2 { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These validity checks are not backed by the spec, and since opencontainers/runtime-spec#780 landed I think the spec is unlikely to add them in the future. Do runtime-tools maintainers intend to reach past runtime-spec and enforce limits that have been silently punted to the kernel (runtime-spec doesn't even have “MUST be a valid value for kernel interface [link]”)? If so, we'll need a validation level for “kernel limits not covered by runtime-spec”. If not, I think we can drop
UnitListValid
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't know the history very well. Why do we remove these limits? These parameters are very related with kernel, if they are not accepted by kernel, that makes no sense, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My impression is that runtime-spec maintainers feel that inlining kernel limits isn't particularly useful. The spec itself has no opinion on these limits, and just punts to the kernel (although I think the wording for the punts still needs work, e.g. opencontainers/runtime-spec#746).
But you could write a config with
foo-bar
as yourlinux.resources.cpu.cpus
value, it would be valid vs. runtime-spec, and if you had a very strange kernel it would actually work for creating a new container. As far as runtime-spec (and our spec-targeting validation here) is concerned, that would be fine. Luckily, the kernel APIs are fairly stable, so config-authors don't have to worry too much about which kernel they're targeting when they figure out these values. And again, if we want to inline these checks with a “kernel limits not covered by runtime-spec” level, I'm fine with that.