diff --git a/cgroups.go b/cgroups.go new file mode 100644 index 000000000..9345f2e30 --- /dev/null +++ b/cgroups.go @@ -0,0 +1,41 @@ +package libcontainer + +import ( + "github.com/docker/libcontainer/cgroups" + "github.com/docker/libcontainer/cgroups/fs" + "github.com/docker/libcontainer/cgroups/systemd" +) + +type CgroupManager interface { + GetPids(*cgroups.Cgroup) ([]int, error) + GetStats(*cgroups.Cgroup) (*cgroups.Stats, error) +} + +func newCgroupsManager() CgroupManager { + if systemd.UseSystemd() { + return &systemdCgroupManager{} + } + return &fsCgroupsManager{} +} + +type systemdCgroupManager struct { +} + +func (m *systemdCgroupManager) GetPids(config *cgroups.Cgroup) ([]int, error) { + return systemd.GetPids(config) +} + +func (m *systemdCgroupManager) GetStats(config *cgroups.Cgroup) (*cgroups.Stats, error) { + return systemd.GetStats(config) +} + +type fsCgroupsManager struct { +} + +func (m *fsCgroupsManager) GetPids(config *cgroups.Cgroup) ([]int, error) { + return fs.GetPids(config) +} + +func (m *fsCgroupsManager) GetStats(config *cgroups.Cgroup) (*cgroups.Stats, error) { + return fs.GetStats(config) +} diff --git a/container.go b/container.go index 42887767a..232f42c45 100644 --- a/container.go +++ b/container.go @@ -12,7 +12,7 @@ type ContainerInfo interface { // errors: // ContainerDestroyed - Container no longer exists, // Systemerror - System error. - RunState() (*RunState, error) + RunState() (RunState, error) // Returns the current config of the container. Config() *Config diff --git a/linux_container.go b/linux_container.go index 112e3e579..1f5e090df 100644 --- a/linux_container.go +++ b/linux_container.go @@ -2,17 +2,14 @@ package libcontainer -import ( - "github.com/docker/libcontainer/cgroups/fs" - "github.com/docker/libcontainer/cgroups/systemd" - "github.com/docker/libcontainer/network" -) +import "github.com/docker/libcontainer/network" type linuxContainer struct { - id string - root string - config *Config - state *State + id string + root string + config *Config + state *State + cgroupManager CgroupManager } func (c *linuxContainer) ID() string { @@ -23,21 +20,12 @@ func (c *linuxContainer) Config() *Config { return c.config } -func (c *linuxContainer) RunState() (*RunState, error) { +func (c *linuxContainer) RunState() (RunState, error) { panic("not implemented") } func (c *linuxContainer) Processes() ([]int, error) { - var ( - err error - pids []int - ) - - if systemd.UseSystemd() { - pids, err = systemd.GetPids(c.config.Cgroups) - } else { - pids, err = fs.GetPids(c.config.Cgroups) - } + pids, err := c.cgroupManager.GetPids(c.config.Cgroups) if err != nil { return nil, newGenericError(err, SystemError) } @@ -50,15 +38,9 @@ func (c *linuxContainer) Stats() (*ContainerStats, error) { stats = &ContainerStats{} ) - if systemd.UseSystemd() { - stats.CgroupStats, err = systemd.GetStats(c.config.Cgroups) - } else { - stats.CgroupStats, err = fs.GetStats(c.config.Cgroups) - } - if err != nil { + if stats.CgroupStats, err = c.cgroupManager.GetStats(c.config.Cgroups); err != nil { return stats, newGenericError(err, SystemError) } - if stats.NetworkStats, err = network.GetStats(&c.state.NetworkState); err != nil { return stats, newGenericError(err, SystemError) } diff --git a/linux_container_test.go b/linux_container_test.go new file mode 100644 index 000000000..85a01cd33 --- /dev/null +++ b/linux_container_test.go @@ -0,0 +1,68 @@ +// +build linux + +package libcontainer + +import ( + "testing" + + "github.com/docker/libcontainer/cgroups" +) + +type mockCgroupManager struct { + pids []int + stats *cgroups.Stats +} + +func (m *mockCgroupManager) GetPids(config *cgroups.Cgroup) ([]int, error) { + return m.pids, nil +} + +func (m *mockCgroupManager) GetStats(config *cgroups.Cgroup) (*cgroups.Stats, error) { + return m.stats, nil +} + +func TestGetContainerPids(t *testing.T) { + container := &linuxContainer{ + id: "myid", + config: &Config{}, + cgroupManager: &mockCgroupManager{pids: []int{1, 2, 3}}, + } + + pids, err := container.Processes() + if err != nil { + t.Fatal(err) + } + + for i, expected := range []int{1, 2, 3} { + if pids[i] != expected { + t.Fatalf("expected pid %d but received %d", expected, pids[i]) + } + } +} + +func TestGetContainerStats(t *testing.T) { + container := &linuxContainer{ + id: "myid", + config: &Config{}, + cgroupManager: &mockCgroupManager{ + pids: []int{1, 2, 3}, + stats: &cgroups.Stats{ + MemoryStats: cgroups.MemoryStats{ + Usage: 1024, + }, + }, + }, + state: &State{}, + } + + stats, err := container.Stats() + if err != nil { + t.Fatal(err) + } + if stats.CgroupStats == nil { + t.Fatal("cgroup stats are nil") + } + if stats.CgroupStats.MemoryStats.Usage != 1024 { + t.Fatalf("expected memory usage 1024 but recevied %d", stats.CgroupStats.MemoryStats.Usage) + } +} diff --git a/linux_factory.go b/linux_factory.go index 9741aa655..989c55285 100644 --- a/linux_factory.go +++ b/linux_factory.go @@ -47,10 +47,11 @@ func (l *linuxFactory) Load(id string) (ContainerInfo, error) { } return &linuxContainer{ - id: id, - root: containerRoot, - config: config, - state: state, + id: id, + root: containerRoot, + config: config, + state: state, + cgroupManager: newCgroupsManager(), }, nil } diff --git a/state.go b/state.go index 208b4c627..4ab47ad75 100644 --- a/state.go +++ b/state.go @@ -31,7 +31,7 @@ const ( stateFile = "state.json" // The container exists and is running. - Running RunState = iota + Running RunState = iota + 1 // The container exists, it is in the process of being paused. Pausing