Merge pull request #253 from avagin/cr-cgroups
c/r: create cgroups to restore a container
This commit is contained in:
commit
ef9471fd5b
|
@ -3,27 +3,16 @@
|
|||
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)
|
||||
cgroups, err := ParseCgroupFile("/proc/self/cgroup")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, ok := cgroups["cpu"]; !ok {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ package cgroups
|
|||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -105,12 +104,12 @@ type Mount struct {
|
|||
Subsystems []string
|
||||
}
|
||||
|
||||
func (m Mount) GetThisCgroupDir() (string, error) {
|
||||
func (m Mount) GetThisCgroupDir(cgroups map[string]string) (string, error) {
|
||||
if len(m.Subsystems) == 0 {
|
||||
return "", fmt.Errorf("no subsystem for mount")
|
||||
}
|
||||
|
||||
return GetThisCgroupDir(m.Subsystems[0])
|
||||
return getControllerPath(m.Subsystems[0], cgroups)
|
||||
}
|
||||
|
||||
func GetCgroupMounts() ([]Mount, error) {
|
||||
|
@ -176,23 +175,22 @@ func GetAllSubsystems() ([]string, error) {
|
|||
|
||||
// Returns the relative path to the cgroup docker is running in.
|
||||
func GetThisCgroupDir(subsystem string) (string, error) {
|
||||
f, err := os.Open("/proc/self/cgroup")
|
||||
cgroups, err := ParseCgroupFile("/proc/self/cgroup")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return ParseCgroupFile(subsystem, f)
|
||||
return getControllerPath(subsystem, cgroups)
|
||||
}
|
||||
|
||||
func GetInitCgroupDir(subsystem string) (string, error) {
|
||||
f, err := os.Open("/proc/1/cgroup")
|
||||
|
||||
cgroups, err := ParseCgroupFile("/proc/1/cgroup")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return ParseCgroupFile(subsystem, f)
|
||||
return getControllerPath(subsystem, cgroups)
|
||||
}
|
||||
|
||||
func ReadProcsFile(dir string) ([]int, error) {
|
||||
|
@ -219,23 +217,40 @@ func ReadProcsFile(dir string) ([]int, error) {
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func ParseCgroupFile(subsystem string, r io.Reader) (string, error) {
|
||||
s := bufio.NewScanner(r)
|
||||
func ParseCgroupFile(path string) (map[string]string, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
s := bufio.NewScanner(f)
|
||||
cgroups := make(map[string]string)
|
||||
|
||||
for s.Scan() {
|
||||
if err := s.Err(); err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
text := s.Text()
|
||||
parts := strings.Split(text, ":")
|
||||
|
||||
for _, subs := range strings.Split(parts[1], ",") {
|
||||
if subs == subsystem || subs == cgroupNamePrefix+subsystem {
|
||||
return parts[2], nil
|
||||
}
|
||||
cgroups[subs] = parts[2]
|
||||
}
|
||||
}
|
||||
return cgroups, nil
|
||||
}
|
||||
|
||||
func getControllerPath(subsystem string, cgroups map[string]string) (string, error) {
|
||||
|
||||
if p, ok := cgroups[subsystem]; ok {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
if p, ok := cgroups[cgroupNamePrefix+subsystem]; ok {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
return "", NewNotFoundError(subsystem)
|
||||
}
|
||||
|
|
|
@ -423,7 +423,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
|
|||
return err
|
||||
}
|
||||
|
||||
err = c.criuSwrk(nil, req, criuOpts)
|
||||
err = c.criuSwrk(nil, req, criuOpts, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -516,6 +516,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
|||
FileLocks: proto.Bool(criuOpts.FileLocks),
|
||||
},
|
||||
}
|
||||
|
||||
for _, m := range c.config.Mounts {
|
||||
switch m.Device {
|
||||
case "bind":
|
||||
|
@ -573,14 +574,36 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
|||
}
|
||||
}
|
||||
|
||||
err = c.criuSwrk(process, req, criuOpts)
|
||||
err = c.criuSwrk(process, req, criuOpts, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts) error {
|
||||
func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
|
||||
if err := c.cgroupManager.Apply(pid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/proc/%d/cgroup", pid)
|
||||
cgroupsPaths, err := cgroups.ParseCgroupFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for c, p := range cgroupsPaths {
|
||||
cgroupRoot := &criurpc.CgroupRoot{
|
||||
Ctrl: proto.String(c),
|
||||
Path: proto.String(p),
|
||||
}
|
||||
req.Opts.CgRoot = append(req.Opts.CgRoot, cgroupRoot)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts, applyCgroups bool) error {
|
||||
fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET|syscall.SOCK_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -614,6 +637,13 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
|
|||
}
|
||||
}()
|
||||
|
||||
if applyCgroups {
|
||||
err := c.criuApplyCgroups(cmd.Process.Pid, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var extFds []string
|
||||
if process != nil {
|
||||
extFds, err = getPipeFds(cmd.Process.Pid)
|
||||
|
|
|
@ -253,10 +253,15 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
cgroupPaths, err := cgroups.ParseCgroupFile("/proc/self/cgroup")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var binds []*configs.Mount
|
||||
|
||||
for _, mm := range mounts {
|
||||
dir, err := mm.GetThisCgroupDir()
|
||||
dir, err := mm.GetThisCgroupDir(cgroupPaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue