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 {