Skip to content

Commit

Permalink
Add code 3.2
Browse files Browse the repository at this point in the history
  • Loading branch information
xianlubird authored and Xianlu committed Jan 11, 2017
1 parent d7511e7 commit 6a066fe
Show file tree
Hide file tree
Showing 12 changed files with 465 additions and 25 deletions.
45 changes: 45 additions & 0 deletions cgroups/cgroup_manager.go
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
}
48 changes: 48 additions & 0 deletions cgroups/subsystems/cpu.go
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"
}

51 changes: 51 additions & 0 deletions cgroups/subsystems/cpuset.go
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"
}
51 changes: 51 additions & 0 deletions cgroups/subsystems/memory.go
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"
}
33 changes: 33 additions & 0 deletions cgroups/subsystems/memory_test.go
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)
}
}
22 changes: 22 additions & 0 deletions cgroups/subsystems/subsystem.go
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{},
}
)
49 changes: 49 additions & 0 deletions cgroups/subsystems/utils.go
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)
}
}
11 changes: 11 additions & 0 deletions cgroups/subsystems/utils_test.go
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"))
}
35 changes: 25 additions & 10 deletions container/container_process.go
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
}
Loading

0 comments on commit 6a066fe

Please sign in to comment.