forked from xianlubird/mydocker
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d7511e7
commit 6a066fe
Showing
12 changed files
with
465 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package cgroups | ||
|
||
import ( | ||
"github.com/xianlubird/mydocker/cgroups/subsystems" | ||
"github.com/Sirupsen/logrus" | ||
) | ||
|
||
type CgroupManager struct { | ||
// cgroup在hierarchy中的路径 相当于创建的cgroup目录相对于root cgroup目录的路径 | ||
Path string | ||
// 资源配置 | ||
Resource *subsystems.ResourceConfig | ||
} | ||
|
||
func NewCgroupManager(path string) *CgroupManager { | ||
return &CgroupManager{ | ||
Path: path, | ||
} | ||
} | ||
|
||
// 将进程pid加入到这个cgroup中 | ||
func (c *CgroupManager) Apply(pid int) error { | ||
for _, subSysIns := range(subsystems.SubsystemsIns) { | ||
subSysIns.Apply(c.Path, pid) | ||
} | ||
return nil | ||
} | ||
|
||
// 设置cgroup资源限制 | ||
func (c *CgroupManager) Set(res *subsystems.ResourceConfig) error { | ||
for _, subSysIns := range(subsystems.SubsystemsIns) { | ||
subSysIns.Set(c.Path, res) | ||
} | ||
return nil | ||
} | ||
|
||
//释放cgroup | ||
func (c *CgroupManager) Destroy() error { | ||
for _, subSysIns := range(subsystems.SubsystemsIns) { | ||
if err := subSysIns.Remove(c.Path); err != nil { | ||
logrus.Warnf("remove cgroup fail %v", err) | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package subsystems | ||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"path" | ||
"os" | ||
"strconv" | ||
) | ||
|
||
type CpuSubSystem struct { | ||
} | ||
|
||
func (s *CpuSubSystem) Set(cgroupPath string, res *ResourceConfig) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, true); err == nil { | ||
if res.CpuShare != "" { | ||
if err := ioutil.WriteFile(path.Join(subsysCgroupPath, "cpu.shares"), []byte(res.CpuShare), 0644); err != nil { | ||
return fmt.Errorf("set cgroup cpu share fail %v", err) | ||
} | ||
} | ||
return nil | ||
} else { | ||
return err | ||
} | ||
} | ||
|
||
func (s *CpuSubSystem) Remove(cgroupPath string) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, false); err == nil { | ||
return os.RemoveAll(subsysCgroupPath) | ||
} else { | ||
return err | ||
} | ||
} | ||
|
||
func (s *CpuSubSystem)Apply(cgroupPath string, pid int) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, false); err == nil { | ||
if err := ioutil.WriteFile(path.Join(subsysCgroupPath, "tasks"), []byte(strconv.Itoa(pid)), 0644); err != nil { | ||
return fmt.Errorf("set cgroup proc fail %v", err) | ||
} | ||
return nil | ||
} else { | ||
return fmt.Errorf("get cgroup %s error: %v", cgroupPath, err) | ||
} | ||
} | ||
|
||
func (s *CpuSubSystem) Name() string { | ||
return "cpu" | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package subsystems | ||
|
||
import( | ||
"fmt" | ||
"io/ioutil" | ||
"path" | ||
"os" | ||
"strconv" | ||
) | ||
|
||
type CpusetSubSystem struct { | ||
|
||
} | ||
|
||
func (s *CpusetSubSystem) Set(cgroupPath string, res *ResourceConfig) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, true); err == nil { | ||
if res.CpuSet != "" { | ||
if err := ioutil.WriteFile(path.Join(subsysCgroupPath, "cpuset.cpus"), []byte(res.CpuSet), 0644); err != nil { | ||
return fmt.Errorf("set cgroup cpuset fail %v", err) | ||
} | ||
} | ||
return nil | ||
} else { | ||
return err | ||
} | ||
} | ||
|
||
func (s *CpusetSubSystem) Remove(cgroupPath string) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, false); err == nil { | ||
return os.RemoveAll(subsysCgroupPath) | ||
} else { | ||
return err | ||
} | ||
} | ||
|
||
|
||
func (s *CpusetSubSystem)Apply(cgroupPath string, pid int) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, false); err == nil { | ||
if err := ioutil.WriteFile(path.Join(subsysCgroupPath, "tasks"), []byte(strconv.Itoa(pid)), 0644); err != nil { | ||
return fmt.Errorf("set cgroup proc fail %v", err) | ||
} | ||
return nil | ||
} else { | ||
return fmt.Errorf("get cgroup %s error: %v", cgroupPath, err) | ||
} | ||
} | ||
|
||
|
||
func (s *CpusetSubSystem) Name() string { | ||
return "cpuset" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package subsystems | ||
|
||
import( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
"strconv" | ||
) | ||
|
||
type MemorySubSystem struct { | ||
} | ||
|
||
func (s *MemorySubSystem) Set(cgroupPath string, res *ResourceConfig) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, true); err == nil { | ||
if res.MemoryLimit != "" { | ||
if err := ioutil.WriteFile(path.Join(subsysCgroupPath, "memory.limit_in_bytes"), []byte(res.MemoryLimit), 0644); err != nil { | ||
return fmt.Errorf("set cgroup memory fail %v", err) | ||
} | ||
} | ||
return nil | ||
} else { | ||
return err | ||
} | ||
|
||
} | ||
|
||
func (s *MemorySubSystem) Remove(cgroupPath string) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, false); err == nil { | ||
return os.RemoveAll(subsysCgroupPath) | ||
} else { | ||
return err | ||
} | ||
} | ||
|
||
|
||
func (s *MemorySubSystem) Apply(cgroupPath string, pid int) error { | ||
if subsysCgroupPath, err := GetCgroupPath(s.Name(), cgroupPath, false); err == nil { | ||
if err := ioutil.WriteFile(path.Join(subsysCgroupPath, "tasks"), []byte(strconv.Itoa(pid)), 0644); err != nil { | ||
return fmt.Errorf("set cgroup proc fail %v", err) | ||
} | ||
return nil | ||
} else { | ||
return fmt.Errorf("get cgroup %s error: %v", cgroupPath, err) | ||
} | ||
} | ||
|
||
|
||
func (s *MemorySubSystem) Name() string { | ||
return "memory" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package subsystems | ||
|
||
import( | ||
"testing" | ||
"os" | ||
"path" | ||
) | ||
|
||
func TestMemoryCgroup(t *testing.T) { | ||
memSubSys := MemorySubSystem{} | ||
resConfig := ResourceConfig{ | ||
MemoryLimit: "1000m", | ||
} | ||
testCgroup := "testmemlimit" | ||
|
||
if err := memSubSys.Set(testCgroup, &resConfig); err != nil { | ||
t.Fatalf("cgroup fail %v", err) | ||
} | ||
stat, _ := os.Stat(path.Join(FindCgroupMountpoint("memory"), testCgroup)) | ||
t.Logf("cgroup stats: %+v", stat) | ||
|
||
if err := memSubSys.Apply(testCgroup, os.Getpid()); err != nil { | ||
t.Fatalf("cgroup Apply %v", err) | ||
} | ||
//将进程移回到根Cgroup节点 | ||
if err := memSubSys.Apply("", os.Getpid()); err != nil { | ||
t.Fatalf("cgroup Apply %v", err) | ||
} | ||
|
||
if err := memSubSys.Remove(testCgroup); err != nil { | ||
t.Fatalf("cgroup remove %v", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package subsystems | ||
|
||
type ResourceConfig struct { | ||
MemoryLimit string | ||
CpuShare string | ||
CpuSet string | ||
} | ||
|
||
type Subsystem interface { | ||
Name() string | ||
Set(path string, res *ResourceConfig) error | ||
Apply(path string, pid int) error | ||
Remove(path string) error | ||
} | ||
|
||
var ( | ||
SubsystemsIns = []Subsystem{ | ||
&CpusetSubSystem{}, | ||
&MemorySubSystem{}, | ||
&CpuSubSystem{}, | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package subsystems | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"os" | ||
"path" | ||
"bufio" | ||
) | ||
|
||
|
||
func FindCgroupMountpoint(subsystem string) string { | ||
f, err := os.Open("/proc/self/mountinfo") | ||
if err != nil { | ||
return "" | ||
} | ||
defer f.Close() | ||
|
||
scanner := bufio.NewScanner(f) | ||
for scanner.Scan() { | ||
txt := scanner.Text() | ||
fields := strings.Split(txt, " ") | ||
for _, opt := range strings.Split(fields[len(fields)-1], ",") { | ||
if opt == subsystem { | ||
return fields[4] | ||
} | ||
} | ||
} | ||
if err := scanner.Err(); err != nil { | ||
return "" | ||
} | ||
|
||
return "" | ||
} | ||
|
||
func GetCgroupPath(subsystem string, cgroupPath string, autoCreate bool) (string, error) { | ||
cgroupRoot := FindCgroupMountpoint(subsystem) | ||
if _, err := os.Stat(path.Join(cgroupRoot, cgroupPath)); err == nil || (autoCreate && os.IsNotExist(err)) { | ||
if os.IsNotExist(err) { | ||
if err := os.Mkdir(path.Join(cgroupRoot, cgroupPath), 0755); err == nil { | ||
} else { | ||
return "", fmt.Errorf("error create cgroup %v", err) | ||
} | ||
} | ||
return path.Join(cgroupRoot, cgroupPath), nil | ||
} else { | ||
return "", fmt.Errorf("cgroup path error %v", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package subsystems | ||
|
||
import( | ||
"testing" | ||
) | ||
|
||
func TestFindCgroupMountpoint(t *testing.T) { | ||
t.Logf("cpu subsystem mount point %v\n", FindCgroupMountpoint("cpu")) | ||
t.Logf("cpuset subsystem mount point %v\n", FindCgroupMountpoint("cpuset")) | ||
t.Logf("memory subsystem mount point %v\n", FindCgroupMountpoint("memory")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,37 @@ | ||
package container | ||
|
||
import ( | ||
"syscall" | ||
"os/exec" | ||
log "github.com/Sirupsen/logrus" | ||
"os" | ||
"os/exec" | ||
"syscall" | ||
) | ||
|
||
func NewParentProcess(tty bool, command string) *exec.Cmd { | ||
args := []string{"init", command} | ||
cmd := exec.Command("/proc/self/exe", args...) | ||
cmd.SysProcAttr = &syscall.SysProcAttr{ | ||
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS | | ||
syscall.CLONE_NEWNET | syscall.CLONE_NEWIPC, | ||
} | ||
func NewParentProcess(tty bool) (*exec.Cmd, *os.File) { | ||
readPipe, writePipe, err := NewPipe() | ||
if err != nil { | ||
log.Errorf("New pipe error %v", err) | ||
return nil, nil | ||
} | ||
cmd := exec.Command("/proc/self/exe", "init") | ||
cmd.SysProcAttr = &syscall.SysProcAttr{ | ||
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS | | ||
syscall.CLONE_NEWNET | syscall.CLONE_NEWIPC, | ||
} | ||
if tty { | ||
cmd.Stdin = os.Stdin | ||
cmd.Stdout = os.Stdout | ||
cmd.Stderr = os.Stderr | ||
} | ||
return cmd | ||
cmd.ExtraFiles = []*os.File{readPipe} | ||
cmd.Dir = "/root/busybox" | ||
return cmd, writePipe | ||
} | ||
|
||
func NewPipe() (*os.File, *os.File, error) { | ||
read, write, err := os.Pipe() | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
return read, write, nil | ||
} |
Oops, something went wrong.