Merge pull request #489 from vmarmol/create
Add container creation time to ContainerSpec.
This commit is contained in:
commit
238a761ffc
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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))
|
||||||
|
Loading…
Reference in New Issue
Block a user