diff --git a/container/docker/handler.go b/container/docker/handler.go index 065b19da..8453d031 100644 --- a/container/docker/handler.go +++ b/container/docker/handler.go @@ -157,12 +157,12 @@ func libcontainerConfigToContainerSpec(config *libcontainer.Config, mi *info.Mac if config.Cgroups.CpuShares != 0 { spec.Cpu.Limit = uint64(config.Cgroups.CpuShares) } - n := (mi.NumCores + 63) / 64 - spec.Cpu.Mask.Data = make([]uint64, n) - for i := 0; i < n; i++ { - spec.Cpu.Mask.Data[i] = math.MaxUint64 + if config.Cgroups.CpusetCpus == "" { + // All cores are active. + spec.Cpu.Mask = fmt.Sprintf("0-%d", mi.NumCores-1) + } else { + spec.Cpu.Mask = config.Cgroups.CpusetCpus } - // TODO(vmarmol): Get CPUs from config.Cgroups.CpusetCpus return spec } diff --git a/container/raw/handler.go b/container/raw/handler.go index 4345f0bf..9988bea5 100644 --- a/container/raw/handler.go +++ b/container/raw/handler.go @@ -15,9 +15,9 @@ package raw import ( + "fmt" "io/ioutil" "log" - "math" "path/filepath" "strconv" "strings" @@ -102,11 +102,7 @@ func (self *rawContainerHandler) GetSpec() (*info.ContainerSpec, error) { spec.Cpu.Limit = readInt64(cpuRoot, "cpu.shares") // TODO(vmarmol): Get CPUs from config.Cgroups.CpusetCpus - n := (mi.NumCores + 63) / 64 - spec.Cpu.Mask.Data = make([]uint64, n) - for i := 0; i < n; i++ { - spec.Cpu.Mask.Data[i] = math.MaxUint64 - } + spec.Cpu.Mask = fmt.Sprintf("0-%d", mi.NumCores-1) } } diff --git a/info/container.go b/info/container.go index 48252a9c..d86bdf96 100644 --- a/info/container.go +++ b/info/container.go @@ -21,14 +21,10 @@ import ( "time" ) -type CpuSpecMask struct { - Data []uint64 `json:"data,omitempty"` -} - type CpuSpec struct { - Limit uint64 `json:"limit"` - MaxLimit uint64 `json:"max_limit"` - Mask CpuSpecMask `json:"mask,omitempty"` + Limit uint64 `json:"limit"` + MaxLimit uint64 `json:"max_limit"` + Mask string `json:"mask,omitempty"` } type MemorySpec struct { diff --git a/pages/containers.go b/pages/containers.go index be7c2e26..6d7b40c9 100644 --- a/pages/containers.go +++ b/pages/containers.go @@ -88,18 +88,12 @@ func containerLink(container info.ContainerReference, basenameOnly bool, cssClas return template.HTML(fmt.Sprintf("%s", cssClasses, ContainersPage[:len(ContainersPage)-1], containerName, displayName)) } -func printMask(mask *info.CpuSpecMask, numCores int) interface{} { - // TODO(vmarmol): Detect this correctly. - // TODO(vmarmol): Support more than 64 cores. - rawMask := uint64(0) - if len(mask.Data) > 0 { - rawMask = mask.Data[0] - } +func printMask(mask string, numCores int) interface{} { masks := make([]string, numCores) - for i := uint(0); i < uint(numCores); i++ { + activeCores := getActiveCores(mask) + for i := 0; i < numCores; i++ { coreClass := "inactive-cpu" - // by default, all cores are active - if ((0x1<%d", coreClass, i) @@ -107,6 +101,34 @@ func printMask(mask *info.CpuSpecMask, numCores int) interface{} { return template.HTML(strings.Join(masks, " ")) } +func getActiveCores(mask string) map[int]bool { + activeCores := make(map[int]bool) + for _, corebits := range strings.Split(mask, ",") { + cores := strings.Split(corebits, "-") + if len(cores) == 1 { + index, err := strconv.Atoi(cores[0]) + if err != nil { + // Ignore malformed strings. + continue + } + activeCores[index] = true + } else if len(cores) == 2 { + start, err := strconv.Atoi(cores[0]) + if err != nil { + continue + } + end, err := strconv.Atoi(cores[1]) + if err != nil { + continue + } + for i := start; i <= end; i++ { + activeCores[i] = true + } + } + } + return activeCores +} + func printCores(millicores *uint64) string { // TODO(vmarmol): Detect this correctly if *millicores > 1024*1000 {