Flatten ContainerSpec.

This commit is contained in:
Victor Marmol 2014-09-19 10:14:22 -07:00
parent 7c59947ee8
commit e22831f1bd
10 changed files with 73 additions and 69 deletions

View File

@ -41,7 +41,7 @@ type SubcontainerEvent struct {
// Interface for container operation handlers. // Interface for container operation handlers.
type ContainerHandler interface { type ContainerHandler interface {
ContainerReference() (info.ContainerReference, error) ContainerReference() (info.ContainerReference, error)
GetSpec() (*info.ContainerSpec, error) GetSpec() (info.ContainerSpec, error)
GetStats() (*info.ContainerStats, error) GetStats() (*info.ContainerStats, error)
ListContainers(listType ListType) ([]info.ContainerReference, error) ListContainers(listType ListType) ([]info.ContainerReference, error)
ListThreads(listType ListType) ([]int, error) ListThreads(listType ListType) ([]int, error)

View File

@ -149,9 +149,9 @@ func (self *dockerContainerHandler) readLibcontainerState() (state *libcontainer
return return
} }
func libcontainerConfigToContainerSpec(config *libcontainer.Config, mi *info.MachineInfo) *info.ContainerSpec { func libcontainerConfigToContainerSpec(config *libcontainer.Config, mi *info.MachineInfo) info.ContainerSpec {
spec := new(info.ContainerSpec) var spec info.ContainerSpec
spec.Memory = new(info.MemorySpec) spec.HasMemory = true
spec.Memory.Limit = math.MaxUint64 spec.Memory.Limit = math.MaxUint64
spec.Memory.SwapLimit = math.MaxUint64 spec.Memory.SwapLimit = math.MaxUint64
if config.Cgroups.Memory > 0 { if config.Cgroups.Memory > 0 {
@ -162,7 +162,7 @@ func libcontainerConfigToContainerSpec(config *libcontainer.Config, mi *info.Mac
} }
// Get CPU info // Get CPU info
spec.Cpu = new(info.CpuSpec) spec.HasCpu = true
spec.Cpu.Limit = 1024 spec.Cpu.Limit = 1024
if config.Cgroups.CpuShares != 0 { if config.Cgroups.CpuShares != 0 {
spec.Cpu.Limit = uint64(config.Cgroups.CpuShares) spec.Cpu.Limit = uint64(config.Cgroups.CpuShares)
@ -173,12 +173,14 @@ func libcontainerConfigToContainerSpec(config *libcontainer.Config, mi *info.Mac
} else { } else {
spec.Cpu.Mask = config.Cgroups.CpusetCpus spec.Cpu.Mask = config.Cgroups.CpusetCpus
} }
spec.HasNetwork = true
return spec return spec
} }
func (self *dockerContainerHandler) GetSpec() (spec *info.ContainerSpec, err error) { func (self *dockerContainerHandler) GetSpec() (spec info.ContainerSpec, err error) {
if self.isDockerRoot() { if self.isDockerRoot() {
return &info.ContainerSpec{}, nil return info.ContainerSpec{}, nil
} }
mi, err := self.machineInfoFactory.GetMachineInfo() mi, err := self.machineInfoFactory.GetMachineInfo()
if err != nil { if err != nil {

View File

@ -44,9 +44,9 @@ func (self *MockContainerHandler) ContainerReference() (info.ContainerReference,
return args.Get(0).(info.ContainerReference), args.Error(1) return args.Get(0).(info.ContainerReference), args.Error(1)
} }
func (self *MockContainerHandler) GetSpec() (*info.ContainerSpec, error) { func (self *MockContainerHandler) GetSpec() (info.ContainerSpec, error) {
args := self.Called() args := self.Called()
return args.Get(0).(*info.ContainerSpec), args.Error(1) return args.Get(0).(info.ContainerSpec), args.Error(1)
} }
func (self *MockContainerHandler) GetStats() (*info.ContainerStats, error) { func (self *MockContainerHandler) GetStats() (*info.ContainerStats, error) {

View File

@ -92,15 +92,15 @@ func readInt64(dirpath string, file string) uint64 {
return val return val
} }
func (self *rawContainerHandler) GetSpec() (*info.ContainerSpec, error) { func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
spec := new(info.ContainerSpec) var spec info.ContainerSpec
// The raw driver assumes unified hierarchy containers. // The raw driver assumes unified hierarchy containers.
// Get machine info. // Get machine info.
mi, err := self.machineInfoFactory.GetMachineInfo() mi, err := self.machineInfoFactory.GetMachineInfo()
if err != nil { if err != nil {
return nil, err return spec, err
} }
// CPU. // CPU.
@ -108,7 +108,7 @@ func (self *rawContainerHandler) GetSpec() (*info.ContainerSpec, error) {
if ok { if ok {
cpuRoot = path.Join(cpuRoot, self.name) cpuRoot = path.Join(cpuRoot, self.name)
if utils.FileExists(cpuRoot) { if utils.FileExists(cpuRoot) {
spec.Cpu = new(info.CpuSpec) spec.HasCpu = true
spec.Cpu.Limit = readInt64(cpuRoot, "cpu.shares") spec.Cpu.Limit = readInt64(cpuRoot, "cpu.shares")
} }
} }
@ -117,11 +117,9 @@ func (self *rawContainerHandler) GetSpec() (*info.ContainerSpec, error) {
// This will fail for non-unified hierarchies. We'll return the whole machine mask in that case. // This will fail for non-unified hierarchies. We'll return the whole machine mask in that case.
cpusetRoot, ok := self.cgroupSubsystems.mountPoints["cpuset"] cpusetRoot, ok := self.cgroupSubsystems.mountPoints["cpuset"]
if ok { if ok {
if spec.Cpu == nil {
spec.Cpu = new(info.CpuSpec)
}
cpusetRoot = path.Join(cpusetRoot, self.name) cpusetRoot = path.Join(cpusetRoot, self.name)
if utils.FileExists(cpusetRoot) { if utils.FileExists(cpusetRoot) {
spec.HasCpu = true
spec.Cpu.Mask = readString(cpusetRoot, "cpuset.cpus") spec.Cpu.Mask = readString(cpusetRoot, "cpuset.cpus")
if spec.Cpu.Mask == "" { if spec.Cpu.Mask == "" {
spec.Cpu.Mask = fmt.Sprintf("0-%d", mi.NumCores-1) spec.Cpu.Mask = fmt.Sprintf("0-%d", mi.NumCores-1)
@ -134,7 +132,7 @@ func (self *rawContainerHandler) GetSpec() (*info.ContainerSpec, error) {
if ok { if ok {
memoryRoot = path.Join(memoryRoot, self.name) memoryRoot = path.Join(memoryRoot, self.name)
if utils.FileExists(memoryRoot) { if utils.FileExists(memoryRoot) {
spec.Memory = new(info.MemorySpec) spec.HasMemory = true
spec.Memory.Limit = readInt64(memoryRoot, "memory.limit_in_bytes") spec.Memory.Limit = readInt64(memoryRoot, "memory.limit_in_bytes")
spec.Memory.SwapLimit = readInt64(memoryRoot, "memory.memsw.limit_in_bytes") spec.Memory.SwapLimit = readInt64(memoryRoot, "memory.memsw.limit_in_bytes")
} }

View File

@ -40,8 +40,13 @@ type MemorySpec struct {
} }
type ContainerSpec struct { type ContainerSpec struct {
Cpu *CpuSpec `json:"cpu,omitempty"` HasCpu bool `json:"has_cpu"`
Memory *MemorySpec `json:"memory,omitempty"` Cpu CpuSpec `json:"cpu,omitempty"`
HasMemory bool `json:"has_memory"`
Memory MemorySpec `json:"memory,omitempty"`
HasNetwork bool `json:"has_network"`
} }
// Container reference contains enough information to uniquely identify a container // Container reference contains enough information to uniquely identify a container
@ -66,7 +71,7 @@ type ContainerInfo struct {
Subcontainers []ContainerReference `json:"subcontainers,omitempty"` Subcontainers []ContainerReference `json:"subcontainers,omitempty"`
// The isolation used in the container. // The isolation used in the container.
Spec *ContainerSpec `json:"spec,omitempty"` Spec ContainerSpec `json:"spec,omitempty"`
// Historical statistics gathered from the container. // Historical statistics gathered from the container.
Stats []*ContainerStats `json:"stats,omitempty"` Stats []*ContainerStats `json:"stats,omitempty"`

View File

@ -51,10 +51,10 @@ func GenerateRandomStats(numStats, numCores int, duration time.Duration) []*info
return ret return ret
} }
func GenerateRandomContainerSpec(numCores int) *info.ContainerSpec { func GenerateRandomContainerSpec(numCores int) info.ContainerSpec {
ret := &info.ContainerSpec{ ret := info.ContainerSpec{
Cpu: &info.CpuSpec{}, Cpu: info.CpuSpec{},
Memory: &info.MemorySpec{}, Memory: info.MemorySpec{},
} }
ret.Cpu.Limit = uint64(1000 + rand.Int63n(2000)) ret.Cpu.Limit = uint64(1000 + rand.Int63n(2000))
ret.Cpu.MaxLimit = uint64(1000 + rand.Int63n(2000)) ret.Cpu.MaxLimit = uint64(1000 + rand.Int63n(2000))

View File

@ -41,7 +41,7 @@ type containerStat struct {
type containerInfo struct { type containerInfo struct {
info.ContainerReference info.ContainerReference
Subcontainers []info.ContainerReference Subcontainers []info.ContainerReference
Spec *info.ContainerSpec Spec info.ContainerSpec
} }
type containerData struct { type containerData struct {
@ -166,7 +166,6 @@ func (c *containerData) housekeeping() {
time.Sleep(nextHousekeeping.Sub(time.Now())) time.Sleep(nextHousekeeping.Sub(time.Now()))
} }
lastHousekeeping = nextHousekeeping lastHousekeeping = nextHousekeeping
} }
} }

View File

@ -166,7 +166,7 @@ func (self *manager) containerDataToContainerInfo(cont *containerData, query *in
} }
// Set default value to an actual value // Set default value to an actual value
if ret.Spec.Memory != nil { if ret.Spec.HasMemory {
// Memory.Limit is 0 means there's no limit // Memory.Limit is 0 means there's no limit
if ret.Spec.Memory.Limit == 0 { if ret.Spec.Memory.Limit == 0 {
ret.Spec.Memory.Limit = uint64(self.machineInfo.MemoryCapacity) ret.Spec.Memory.Limit = uint64(self.machineInfo.MemoryCapacity)

View File

@ -108,7 +108,7 @@ type pageData struct {
ContainerName string ContainerName string
ParentContainers []info.ContainerReference ParentContainers []info.ContainerReference
Subcontainers []info.ContainerReference Subcontainers []info.ContainerReference
Spec *info.ContainerSpec Spec info.ContainerSpec
Stats []*info.ContainerStats Stats []*info.ContainerStats
MachineInfo *info.MachineInfo MachineInfo *info.MachineInfo
ResourcesAvailable bool ResourcesAvailable bool
@ -300,14 +300,6 @@ func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL)
} }
} }
networkStatsAvailable := false
for _, stat := range cont.Stats {
if stat.Network != nil {
networkStatsAvailable = true
break
}
}
data := &pageData{ data := &pageData{
ContainerName: displayName, ContainerName: displayName,
// TODO(vmarmol): Only use strings for this. // TODO(vmarmol): Only use strings for this.
@ -316,10 +308,10 @@ func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL)
Spec: cont.Spec, Spec: cont.Spec,
Stats: cont.Stats, Stats: cont.Stats,
MachineInfo: machineInfo, MachineInfo: machineInfo,
ResourcesAvailable: cont.Spec.Cpu != nil || cont.Spec.Memory != nil, ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
CpuAvailable: cont.Spec.Cpu != nil, CpuAvailable: cont.Spec.HasCpu,
MemoryAvailable: cont.Spec.Memory != nil, MemoryAvailable: cont.Spec.HasMemory,
NetworkAvailable: networkStatsAvailable, NetworkAvailable: cont.Spec.HasNetwork,
} }
err = pageTemplate.Execute(w, data) err = pageTemplate.Execute(w, data)
if err != nil { if err != nil {

View File

@ -142,7 +142,7 @@ function getStats(containerName, callback) {
// Draw the graph for CPU usage. // Draw the graph for CPU usage.
function drawCpuTotalUsage(elementId, machineInfo, stats) { function drawCpuTotalUsage(elementId, machineInfo, stats) {
if (!hasResource(stats, "cpu")) { if (stats.spec.has_cpu && !hasResource(stats, "cpu")) {
return; return;
} }
@ -163,7 +163,7 @@ function drawCpuTotalUsage(elementId, machineInfo, stats) {
// Draw the graph for per-core CPU usage. // Draw the graph for per-core CPU usage.
function drawCpuPerCoreUsage(elementId, machineInfo, stats) { function drawCpuPerCoreUsage(elementId, machineInfo, stats) {
if (!hasResource(stats, "cpu")) { if (stats.spec.has_cpu && !hasResource(stats, "cpu")) {
return; return;
} }
@ -190,7 +190,7 @@ function drawCpuPerCoreUsage(elementId, machineInfo, stats) {
// Draw the graph for CPU usage breakdown. // Draw the graph for CPU usage breakdown.
function drawCpuUsageBreakdown(elementId, containerInfo) { function drawCpuUsageBreakdown(elementId, containerInfo) {
if (!hasResource(containerInfo, "cpu")) { if (containerInfo.spec.has_cpu && !hasResource(containerInfo, "cpu")) {
return; return;
} }
@ -215,7 +215,7 @@ function drawOverallUsage(elementId, machineInfo, containerInfo) {
var cur = containerInfo.stats[containerInfo.stats.length - 1]; var cur = containerInfo.stats[containerInfo.stats.length - 1];
var cpuUsage = 0; var cpuUsage = 0;
if (containerInfo.spec.cpu && containerInfo.stats.length >= 2) { if (containerInfo.spec.has_cpu && containerInfo.stats.length >= 2) {
var prev = containerInfo.stats[containerInfo.stats.length - 2]; var prev = containerInfo.stats[containerInfo.stats.length - 2];
var rawUsage = cur.cpu.usage.total - prev.cpu.usage.total; var rawUsage = cur.cpu.usage.total - prev.cpu.usage.total;
var intervalInNs = getInterval(cur.timestamp, prev.timestamp); var intervalInNs = getInterval(cur.timestamp, prev.timestamp);
@ -228,7 +228,7 @@ function drawOverallUsage(elementId, machineInfo, containerInfo) {
} }
var memoryUsage = 0; var memoryUsage = 0;
if (containerInfo.spec.memory) { if (containerInfo.spec.has_memory) {
// Saturate to the machine size. // Saturate to the machine size.
var limit = containerInfo.spec.memory.limit; var limit = containerInfo.spec.memory.limit;
if (limit > machineInfo.memory_capacity) { if (limit > machineInfo.memory_capacity) {
@ -244,7 +244,7 @@ function drawOverallUsage(elementId, machineInfo, containerInfo) {
var oneMegabyte = 1024 * 1024; var oneMegabyte = 1024 * 1024;
function drawMemoryUsage(elementId, containerInfo) { function drawMemoryUsage(elementId, containerInfo) {
if (!hasResource(containerInfo, "memory")) { if (containerInfo.spec.has_memory && !hasResource(containerInfo, "memory")) {
return; return;
} }
@ -264,7 +264,7 @@ function drawMemoryUsage(elementId, containerInfo) {
// Draw the graph for network tx/rx bytes. // Draw the graph for network tx/rx bytes.
function drawNetworkBytes(elementId, machineInfo, stats) { function drawNetworkBytes(elementId, machineInfo, stats) {
if (!hasResource(stats, "network")) { if (stats.spec.has_network && !hasResource(stats, "network")) {
return; return;
} }
@ -286,7 +286,7 @@ function drawNetworkBytes(elementId, machineInfo, stats) {
// Draw the graph for network errors // Draw the graph for network errors
function drawNetworkErrors(elementId, machineInfo, stats) { function drawNetworkErrors(elementId, machineInfo, stats) {
if (!hasResource(stats, "network")) { if (stats.spec.has_network && !hasResource(stats, "network")) {
return; return;
} }
@ -328,11 +328,14 @@ function stepExecute(steps) {
function drawCharts(machineInfo, containerInfo) { function drawCharts(machineInfo, containerInfo) {
var steps = []; var steps = [];
if (containerInfo.spec.has_cpu || containerInfo.spec.has_memory) {
steps.push(function() { steps.push(function() {
drawOverallUsage("usage-gauge", machineInfo, containerInfo) drawOverallUsage("usage-gauge", machineInfo, containerInfo)
}); });
}
// CPU. // CPU.
if (containerInfo.spec.has_cpu) {
steps.push(function() { steps.push(function() {
drawCpuTotalUsage("cpu-total-usage-chart", machineInfo, containerInfo); drawCpuTotalUsage("cpu-total-usage-chart", machineInfo, containerInfo);
}); });
@ -342,19 +345,24 @@ function drawCharts(machineInfo, containerInfo) {
steps.push(function() { steps.push(function() {
drawCpuUsageBreakdown("cpu-usage-breakdown-chart", containerInfo); drawCpuUsageBreakdown("cpu-usage-breakdown-chart", containerInfo);
}); });
}
// Memory. // Memory.
if (containerInfo.spec.has_memory) {
steps.push(function() { steps.push(function() {
drawMemoryUsage("memory-usage-chart", containerInfo); drawMemoryUsage("memory-usage-chart", containerInfo);
}); });
}
// Network. // Network.
if (containerInfo.spec.has_network) {
steps.push(function() { steps.push(function() {
drawNetworkBytes("network-bytes-chart", machineInfo, containerInfo); drawNetworkBytes("network-bytes-chart", machineInfo, containerInfo);
}); });
steps.push(function() { steps.push(function() {
drawNetworkErrors("network-errors-chart", machineInfo, containerInfo); drawNetworkErrors("network-errors-chart", machineInfo, containerInfo);
}); });
}
stepExecute(steps); stepExecute(steps);
} }