Merge pull request #489 from vmarmol/create

Add container creation time to ContainerSpec.
This commit is contained in:
Rohit Jnagal 2015-02-05 10:38:59 -08:00
commit 238a761ffc
4 changed files with 66 additions and 9 deletions

View File

@ -23,6 +23,7 @@ import (
"os" "os"
"path" "path"
"strings" "strings"
"time"
"github.com/docker/libcontainer" "github.com/docker/libcontainer"
"github.com/docker/libcontainer/cgroups" "github.com/docker/libcontainer/cgroups"
@ -68,6 +69,9 @@ type dockerContainerHandler struct {
usesAufsDriver bool usesAufsDriver bool
fsInfo fs.FsInfo fsInfo fs.FsInfo
storageDirs []string storageDirs []string
// Time at which this container was created.
creationTime time.Time
} }
func DockerStateDir() string { func DockerStateDir() string {
@ -119,6 +123,7 @@ func newDockerContainerHandler(
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to inspect container %q: %v", id, err) return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
} }
handler.creationTime = ctnr.Created
// Add the name and bare ID as aliases of the container. // Add the name and bare ID as aliases of the container.
handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/")) handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"))
@ -235,23 +240,23 @@ func libcontainerConfigToContainerSpec(config *libcontainer.Config, mi *info.Mac
return spec return spec
} }
func (self *dockerContainerHandler) GetSpec() (spec info.ContainerSpec, err error) { func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
mi, err := self.machineInfoFactory.GetMachineInfo() mi, err := self.machineInfoFactory.GetMachineInfo()
if err != nil { if err != nil {
return return info.ContainerSpec{}, err
} }
libcontainerConfig, err := self.readLibcontainerConfig() libcontainerConfig, err := self.readLibcontainerConfig()
if err != nil { if err != nil {
return return info.ContainerSpec{}, err
} }
spec = libcontainerConfigToContainerSpec(libcontainerConfig, mi) spec := libcontainerConfigToContainerSpec(libcontainerConfig, mi)
spec.CreationTime = self.creationTime
if self.usesAufsDriver { if self.usesAufsDriver {
spec.HasFilesystem = true spec.HasFilesystem = true
} }
return return spec, err
} }
func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error { func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error {

View File

@ -18,9 +18,11 @@ package raw
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"path" "path"
"strconv" "strconv"
"strings" "strings"
"time"
"code.google.com/p/go.exp/inotify" "code.google.com/p/go.exp/inotify"
dockerlibcontainer "github.com/docker/libcontainer" dockerlibcontainer "github.com/docker/libcontainer"
@ -180,6 +182,20 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
// The raw driver assumes unified hierarchy containers. // The raw driver assumes unified hierarchy containers.
// Get the lowest creation time from all hierarchies as the container creation time.
now := time.Now()
lowestTime := now
for _, cgroupPath := range self.cgroupPaths {
// The modified time of the cgroup directory is when the container was created.
fi, err := os.Stat(cgroupPath)
if err == nil && fi.ModTime().Before(lowestTime) {
lowestTime = fi.ModTime()
}
}
if lowestTime != now {
spec.CreationTime = lowestTime
}
// Get machine info. // Get machine info.
mi, err := self.machineInfoFactory.GetMachineInfo() mi, err := self.machineInfoFactory.GetMachineInfo()
if err != nil { if err != nil {

View File

@ -40,6 +40,9 @@ type MemorySpec struct {
} }
type ContainerSpec struct { type ContainerSpec struct {
// Time at which the container was created.
CreationTime time.Time `json:"creation_time,omitempty"`
HasCpu bool `json:"has_cpu"` HasCpu bool `json:"has_cpu"`
Cpu CpuSpec `json:"cpu,omitempty"` Cpu CpuSpec `json:"cpu,omitempty"`
@ -88,6 +91,7 @@ type ContainerInfo struct {
Stats []*ContainerStats `json:"stats,omitempty"` Stats []*ContainerStats `json:"stats,omitempty"`
} }
// TODO(vmarmol): Refactor to not need this equality comparison.
// ContainerInfo may be (un)marshaled by json or other en/decoder. In that // ContainerInfo may be (un)marshaled by json or other en/decoder. In that
// case, the Timestamp field in each stats/sample may not be precisely // case, the Timestamp field in each stats/sample may not be precisely
// en/decoded. This will lead to small but acceptable differences between a // en/decoded. This will lead to small but acceptable differences between a
@ -111,7 +115,7 @@ func (self *ContainerInfo) Eq(b *ContainerInfo) bool {
if !reflect.DeepEqual(self.Subcontainers, b.Subcontainers) { if !reflect.DeepEqual(self.Subcontainers, b.Subcontainers) {
return false return false
} }
if !reflect.DeepEqual(self.Spec, b.Spec) { if !self.Spec.Eq(&b.Spec) {
return false return false
} }
@ -125,6 +129,37 @@ func (self *ContainerInfo) Eq(b *ContainerInfo) bool {
return true return true
} }
func (self *ContainerSpec) Eq(b *ContainerSpec) bool {
// Creation within 1s of each other.
diff := self.CreationTime.Sub(b.CreationTime)
if (diff > time.Second) || (diff < -time.Second) {
return false
}
if self.HasCpu != b.HasCpu {
return false
}
if !reflect.DeepEqual(self.Cpu, b.Cpu) {
return false
}
if self.HasMemory != b.HasMemory {
return false
}
if !reflect.DeepEqual(self.Memory, b.Memory) {
return false
}
if self.HasNetwork != b.HasNetwork {
return false
}
if self.HasFilesystem != b.HasFilesystem {
return false
}
if self.HasDiskIo != b.HasDiskIo {
return false
}
return true
}
func (self *ContainerInfo) StatsAfter(ref time.Time) []*ContainerStats { func (self *ContainerInfo) StatsAfter(ref time.Time) []*ContainerStats {
n := len(self.Stats) + 1 n := len(self.Stats) + 1
for i, s := range self.Stats { for i, s := range self.Stats {

View File

@ -51,8 +51,9 @@ func GenerateRandomStats(numStats, numCores int, duration time.Duration) []*info
func GenerateRandomContainerSpec(numCores int) info.ContainerSpec { func GenerateRandomContainerSpec(numCores int) info.ContainerSpec {
ret := info.ContainerSpec{ ret := info.ContainerSpec{
Cpu: info.CpuSpec{}, CreationTime: time.Now(),
Memory: info.MemorySpec{}, Cpu: info.CpuSpec{},
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))