From 13860a3ba98883058057672f6aef89b5af37f2f9 Mon Sep 17 00:00:00 2001 From: Paul Nasrat Date: Mon, 20 Jan 2014 14:15:44 -0500 Subject: [PATCH] Extract cgroups pkg. Initial move before enhancing cgroups package. Docker-DCO-1.1-Signed-off-by: Paul Nasrat (github: pnasrat) --- cgroups/MAINTAINERS | 1 + cgroups/cgroups.go | 106 ++++++++++++++++++++++++++++++++++++++++ cgroups/cgroups_test.go | 27 ++++++++++ sysinfo/sysinfo.go | 2 +- 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 cgroups/MAINTAINERS create mode 100644 cgroups/cgroups.go create mode 100644 cgroups/cgroups_test.go diff --git a/cgroups/MAINTAINERS b/cgroups/MAINTAINERS new file mode 100644 index 0000000..1e998f8 --- /dev/null +++ b/cgroups/MAINTAINERS @@ -0,0 +1 @@ +Michael Crosby (@crosbymichael) diff --git a/cgroups/cgroups.go b/cgroups/cgroups.go new file mode 100644 index 0000000..07867a6 --- /dev/null +++ b/cgroups/cgroups.go @@ -0,0 +1,106 @@ +package cgroups + +import ( + "bufio" + "fmt" + "github.com/dotcloud/docker/pkg/mount" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" +) + +type Values struct { + Memory int64 `json:"memory"` + MemorySwap int64 `json:"memory_swap"` + CpuShares int64 `json:"cpu_shares"` +} + +// https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt +func FindCgroupMountpoint(subsystem string) (string, error) { + mounts, err := mount.GetMounts() + if err != nil { + return "", err + } + + for _, mount := range mounts { + if mount.Fstype == "cgroup" { + for _, opt := range strings.Split(mount.VfsOpts, ",") { + if opt == subsystem { + return mount.Mountpoint, nil + } + } + } + } + + return "", fmt.Errorf("cgroup mountpoint not found for %s", subsystem) +} + +// Returns the relative path to the cgroup docker is running in. +func getThisCgroupDir(subsystem string) (string, error) { + f, err := os.Open("/proc/self/cgroup") + if err != nil { + return "", err + } + defer f.Close() + + return parseCgroupFile(subsystem, f) +} + +func parseCgroupFile(subsystem string, r io.Reader) (string, error) { + s := bufio.NewScanner(r) + + for s.Scan() { + if err := s.Err(); err != nil { + return "", err + } + text := s.Text() + parts := strings.Split(text, ":") + if parts[1] == subsystem { + return parts[2], nil + } + } + return "", fmt.Errorf("cgroup '%s' not found in /proc/self/cgroup", subsystem) +} + +// Returns a list of pids for the given container. +func GetPidsForContainer(id string) ([]int, error) { + pids := []int{} + + // memory is chosen randomly, any cgroup used by docker works + subsystem := "memory" + + cgroupRoot, err := FindCgroupMountpoint(subsystem) + if err != nil { + return pids, err + } + + cgroupDir, err := getThisCgroupDir(subsystem) + if err != nil { + return pids, err + } + + filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks") + if _, err := os.Stat(filename); os.IsNotExist(err) { + // With more recent lxc versions use, cgroup will be in lxc/ + filename = filepath.Join(cgroupRoot, cgroupDir, "lxc", id, "tasks") + } + + output, err := ioutil.ReadFile(filename) + if err != nil { + return pids, err + } + for _, p := range strings.Split(string(output), "\n") { + if len(p) == 0 { + continue + } + pid, err := strconv.Atoi(p) + if err != nil { + return pids, fmt.Errorf("Invalid pid '%s': %s", p, err) + } + pids = append(pids, pid) + } + return pids, nil +} diff --git a/cgroups/cgroups_test.go b/cgroups/cgroups_test.go new file mode 100644 index 0000000..537336a --- /dev/null +++ b/cgroups/cgroups_test.go @@ -0,0 +1,27 @@ +package cgroups + +import ( + "bytes" + "testing" +) + +const ( + cgroupsContents = `11:hugetlb:/ +10:perf_event:/ +9:blkio:/ +8:net_cls:/ +7:freezer:/ +6:devices:/ +5:memory:/ +4:cpuacct,cpu:/ +3:cpuset:/ +2:name=systemd:/user.slice/user-1000.slice/session-16.scope` +) + +func TestParseCgroups(t *testing.T) { + r := bytes.NewBuffer([]byte(cgroupsContents)) + _, err := parseCgroupFile("blkio", r) + if err != nil { + t.Fatal(err) + } +} diff --git a/sysinfo/sysinfo.go b/sysinfo/sysinfo.go index f9bd6b8..b3463f8 100644 --- a/sysinfo/sysinfo.go +++ b/sysinfo/sysinfo.go @@ -1,7 +1,7 @@ package sysinfo import ( - "github.com/dotcloud/docker/cgroups" // FIXME: move cgroups in pkg + "github.com/dotcloud/docker/pkg/cgroups" "io/ioutil" "log" "os"