Bladeren bron

Merge pull request #5976 from crosbymichael/getpids

Move get pid into cgroup implementation
Victor Vieux 11 jaren geleden
bovenliggende
commit
55d41c3e21

+ 10 - 3
daemon/execdriver/native/create.go

@@ -3,6 +3,7 @@ package native
 import (
 	"fmt"
 	"os"
+	"os/exec"
 	"path/filepath"
 
 	"github.com/dotcloud/docker/daemon/execdriver"
@@ -45,7 +46,11 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Container
 	if err := d.setupLabels(container, c); err != nil {
 		return nil, err
 	}
-	if err := configuration.ParseConfiguration(container, d.activeContainers, c.Config["native"]); err != nil {
+	cmds := make(map[string]*exec.Cmd)
+	for k, v := range d.activeContainers {
+		cmds[k] = v.cmd
+	}
+	if err := configuration.ParseConfiguration(container, cmds, c.Config["native"]); err != nil {
 		return nil, err
 	}
 	return container, nil
@@ -81,10 +86,12 @@ func (d *driver) createNetwork(container *libcontainer.Container, c *execdriver.
 	}
 
 	if c.Network.ContainerID != "" {
-		cmd := d.activeContainers[c.Network.ContainerID]
-		if cmd == nil || cmd.Process == nil {
+		active := d.activeContainers[c.Network.ContainerID]
+		if active == nil || active.cmd.Process == nil {
 			return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
 		}
+		cmd := active.cmd
+
 		nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
 		container.Networks = append(container.Networks, &libcontainer.Network{
 			Type: "netns",

+ 24 - 35
daemon/execdriver/native/driver.go

@@ -7,14 +7,14 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
-	"strconv"
 	"strings"
 	"syscall"
 
 	"github.com/dotcloud/docker/daemon/execdriver"
 	"github.com/dotcloud/docker/pkg/apparmor"
 	"github.com/dotcloud/docker/pkg/libcontainer"
-	"github.com/dotcloud/docker/pkg/libcontainer/cgroups"
+	"github.com/dotcloud/docker/pkg/libcontainer/cgroups/fs"
+	"github.com/dotcloud/docker/pkg/libcontainer/cgroups/systemd"
 	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
 	"github.com/dotcloud/docker/pkg/system"
 )
@@ -53,24 +53,31 @@ func init() {
 	})
 }
 
+type activeContainer struct {
+	container *libcontainer.Container
+	cmd       *exec.Cmd
+}
+
 type driver struct {
 	root             string
 	initPath         string
-	activeContainers map[string]*exec.Cmd
+	activeContainers map[string]*activeContainer
 }
 
 func NewDriver(root, initPath string) (*driver, error) {
 	if err := os.MkdirAll(root, 0700); err != nil {
 		return nil, err
 	}
+
 	// native driver root is at docker_root/execdriver/native. Put apparmor at docker_root
 	if err := apparmor.InstallDefaultProfile(filepath.Join(root, "../..", BackupApparmorProfilePath)); err != nil {
 		return nil, err
 	}
+
 	return &driver{
 		root:             root,
 		initPath:         initPath,
-		activeContainers: make(map[string]*exec.Cmd),
+		activeContainers: make(map[string]*activeContainer),
 	}, nil
 }
 
@@ -80,7 +87,10 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
 	if err != nil {
 		return -1, err
 	}
-	d.activeContainers[c.ID] = &c.Cmd
+	d.activeContainers[c.ID] = &activeContainer{
+		container: container,
+		cmd:       &c.Cmd,
+	}
 
 	var (
 		dataPath = filepath.Join(d.root, c.ID)
@@ -175,41 +185,18 @@ func (d *driver) Name() string {
 	return fmt.Sprintf("%s-%s", DriverName, Version)
 }
 
-// TODO: this can be improved with our driver
-// there has to be a better way to do this
 func (d *driver) GetPidsForContainer(id string) ([]int, error) {
-	pids := []int{}
-
-	subsystem := "devices"
-	cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem)
-	if err != nil {
-		return pids, err
-	}
-	cgroupDir, err := cgroups.GetThisCgroupDir(subsystem)
-	if err != nil {
-		return pids, err
-	}
+	active := d.activeContainers[id]
 
-	filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks")
-	if _, err := os.Stat(filename); os.IsNotExist(err) {
-		filename = filepath.Join(cgroupRoot, cgroupDir, "docker", id, "tasks")
+	if active == nil {
+		return nil, fmt.Errorf("active container for %s does not exist", id)
 	}
+	c := active.container.Cgroups
 
-	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)
+	if systemd.UseSystemd() {
+		return systemd.GetPids(c)
 	}
-	return pids, nil
+	return fs.GetPids(c)
 }
 
 func (d *driver) writeContainerFile(container *libcontainer.Container, id string) error {
@@ -225,6 +212,8 @@ func (d *driver) createContainerRoot(id string) error {
 }
 
 func (d *driver) removeContainerRoot(id string) error {
+	delete(d.activeContainers, id)
+
 	return os.RemoveAll(filepath.Join(d.root, id))
 }
 

+ 30 - 0
pkg/libcontainer/cgroups/fs/apply_raw.go

@@ -103,6 +103,36 @@ func GetStats(c *cgroups.Cgroup, subsystem string, pid int) (map[string]float64,
 	return sys.Stats(d)
 }
 
+func GetPids(c *cgroups.Cgroup) ([]int, error) {
+	cgroupRoot, err := cgroups.FindCgroupMountpoint("cpu")
+	if err != nil {
+		return nil, err
+	}
+	cgroupRoot = filepath.Dir(cgroupRoot)
+
+	if _, err := os.Stat(cgroupRoot); err != nil {
+		return nil, fmt.Errorf("cgroup root %s not found", cgroupRoot)
+	}
+
+	cgroup := c.Name
+	if c.Parent != "" {
+		cgroup = filepath.Join(c.Parent, cgroup)
+	}
+
+	d := &data{
+		root:   cgroupRoot,
+		cgroup: cgroup,
+		c:      c,
+	}
+
+	dir, err := d.path("devices")
+	if err != nil {
+		return nil, err
+	}
+
+	return cgroups.ReadProcsFile(dir)
+}
+
 func (raw *data) parent(subsystem string) (string, error) {
 	initPath, err := cgroups.GetInitCgroupDir(subsystem)
 	if err != nil {

+ 0 - 9
pkg/libcontainer/cgroups/fs/devices.go

@@ -1,9 +1,5 @@
 package fs
 
-import (
-	"os"
-)
-
 type devicesGroup struct {
 }
 
@@ -12,11 +8,6 @@ func (s *devicesGroup) Set(d *data) error {
 	if err != nil {
 		return err
 	}
-	defer func() {
-		if err != nil {
-			os.RemoveAll(dir)
-		}
-	}()
 
 	if !d.c.DeviceAccess {
 		if err := writeFile(dir, "devices.deny", "a"); err != nil {

+ 5 - 1
pkg/libcontainer/cgroups/systemd/apply_nosystemd.go

@@ -12,6 +12,10 @@ func UseSystemd() bool {
 	return false
 }
 
-func Apply(c *Cgroup, pid int) (cgroups.ActiveCgroup, error) {
+func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
+	return nil, fmt.Errorf("Systemd not supported")
+}
+
+func GetPids(c *cgroups.Cgroup) ([]int, error) {
 	return nil, fmt.Errorf("Systemd not supported")
 }

+ 23 - 1
pkg/libcontainer/cgroups/systemd/apply_systemd.go

@@ -3,6 +3,7 @@
 package systemd
 
 import (
+	"fmt"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -78,7 +79,7 @@ type cgroupArg struct {
 
 func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
 	var (
-		unitName   = c.Parent + "-" + c.Name + ".scope"
+		unitName   = getUnitName(c)
 		slice      = "system.slice"
 		properties []systemd1.Property
 		cpuArgs    []cgroupArg
@@ -303,3 +304,24 @@ func (c *systemdCgroup) Cleanup() error {
 
 	return nil
 }
+
+func GetPids(c *cgroups.Cgroup) ([]int, error) {
+	unitName := getUnitName(c)
+
+	mountpoint, err := cgroups.FindCgroupMountpoint("cpu")
+	if err != nil {
+		return nil, err
+	}
+
+	props, err := theConn.GetUnitTypeProperties(unitName, getIfaceForUnit(unitName))
+	if err != nil {
+		return nil, err
+	}
+	cgroup := props["ControlGroup"].(string)
+
+	return cgroups.ReadProcsFile(filepath.Join(mountpoint, cgroup))
+}
+
+func getUnitName(c *cgroups.Cgroup) string {
+	return fmt.Sprintf("%s-%s.scope", c.Parent, c.Name)
+}

+ 26 - 0
pkg/libcontainer/cgroups/utils.go

@@ -4,6 +4,8 @@ import (
 	"bufio"
 	"io"
 	"os"
+	"path/filepath"
+	"strconv"
 	"strings"
 
 	"github.com/dotcloud/docker/pkg/mount"
@@ -49,6 +51,30 @@ func GetInitCgroupDir(subsystem string) (string, error) {
 	return parseCgroupFile(subsystem, f)
 }
 
+func ReadProcsFile(dir string) ([]int, error) {
+	f, err := os.Open(filepath.Join(dir, "cgroup.procs"))
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	var (
+		s   = bufio.NewScanner(f)
+		out = []int{}
+	)
+
+	for s.Scan() {
+		if t := s.Text(); t != "" {
+			pid, err := strconv.Atoi(t)
+			if err != nil {
+				return nil, err
+			}
+			out = append(out, pid)
+		}
+	}
+	return out, nil
+}
+
 func parseCgroupFile(subsystem string, r io.Reader) (string, error) {
 	s := bufio.NewScanner(r)
 	for s.Scan() {