mirror of https://github.com/docker/docs.git
Move get pid into cgroup implementation
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
parent
29a192ca4d
commit
811d93326b
|
@ -3,6 +3,7 @@ package native
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/dotcloud/docker/daemon/execdriver"
|
"github.com/dotcloud/docker/daemon/execdriver"
|
||||||
|
@ -46,7 +47,11 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Container
|
||||||
if err := d.setupLabels(container, c); err != nil {
|
if err := d.setupLabels(container, c); err != nil {
|
||||||
return nil, err
|
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 nil, err
|
||||||
}
|
}
|
||||||
return container, nil
|
return container, nil
|
||||||
|
@ -82,10 +87,12 @@ func (d *driver) createNetwork(container *libcontainer.Container, c *execdriver.
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Network.ContainerID != "" {
|
if c.Network.ContainerID != "" {
|
||||||
cmd := d.activeContainers[c.Network.ContainerID]
|
active := d.activeContainers[c.Network.ContainerID]
|
||||||
if cmd == nil || cmd.Process == nil {
|
if active == nil || active.cmd.Process == nil {
|
||||||
return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
|
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")
|
nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
|
||||||
container.Networks = append(container.Networks, &libcontainer.Network{
|
container.Networks = append(container.Networks, &libcontainer.Network{
|
||||||
Type: "netns",
|
Type: "netns",
|
||||||
|
|
|
@ -7,14 +7,14 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/dotcloud/docker/daemon/execdriver"
|
"github.com/dotcloud/docker/daemon/execdriver"
|
||||||
"github.com/dotcloud/docker/pkg/apparmor"
|
"github.com/dotcloud/docker/pkg/apparmor"
|
||||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
"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/libcontainer/nsinit"
|
||||||
"github.com/dotcloud/docker/pkg/system"
|
"github.com/dotcloud/docker/pkg/system"
|
||||||
)
|
)
|
||||||
|
@ -53,24 +53,31 @@ func init() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type activeContainer struct {
|
||||||
|
container *libcontainer.Container
|
||||||
|
cmd *exec.Cmd
|
||||||
|
}
|
||||||
|
|
||||||
type driver struct {
|
type driver struct {
|
||||||
root string
|
root string
|
||||||
initPath string
|
initPath string
|
||||||
activeContainers map[string]*exec.Cmd
|
activeContainers map[string]*activeContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDriver(root, initPath string) (*driver, error) {
|
func NewDriver(root, initPath string) (*driver, error) {
|
||||||
if err := os.MkdirAll(root, 0700); err != nil {
|
if err := os.MkdirAll(root, 0700); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// native driver root is at docker_root/execdriver/native. Put apparmor at docker_root
|
// native driver root is at docker_root/execdriver/native. Put apparmor at docker_root
|
||||||
if err := apparmor.InstallDefaultProfile(filepath.Join(root, "../..", BackupApparmorProfilePath)); err != nil {
|
if err := apparmor.InstallDefaultProfile(filepath.Join(root, "../..", BackupApparmorProfilePath)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &driver{
|
return &driver{
|
||||||
root: root,
|
root: root,
|
||||||
initPath: initPath,
|
initPath: initPath,
|
||||||
activeContainers: make(map[string]*exec.Cmd),
|
activeContainers: make(map[string]*activeContainer),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +87,10 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
d.activeContainers[c.ID] = &c.Cmd
|
d.activeContainers[c.ID] = &activeContainer{
|
||||||
|
container: container,
|
||||||
|
cmd: &c.Cmd,
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dataPath = filepath.Join(d.root, c.ID)
|
dataPath = filepath.Join(d.root, c.ID)
|
||||||
|
@ -175,41 +185,18 @@ func (d *driver) Name() string {
|
||||||
return fmt.Sprintf("%s-%s", DriverName, Version)
|
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) {
|
func (d *driver) GetPidsForContainer(id string) ([]int, error) {
|
||||||
pids := []int{}
|
active := d.activeContainers[id]
|
||||||
|
|
||||||
subsystem := "devices"
|
if active == nil {
|
||||||
cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem)
|
return nil, fmt.Errorf("active container for %s does not exist", id)
|
||||||
if err != nil {
|
|
||||||
return pids, err
|
|
||||||
}
|
|
||||||
cgroupDir, err := cgroups.GetThisCgroupDir(subsystem)
|
|
||||||
if err != nil {
|
|
||||||
return pids, err
|
|
||||||
}
|
}
|
||||||
|
c := active.container.Cgroups
|
||||||
|
|
||||||
filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks")
|
if systemd.UseSystemd() {
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
return systemd.GetPids(c)
|
||||||
filename = filepath.Join(cgroupRoot, cgroupDir, "docker", id, "tasks")
|
|
||||||
}
|
}
|
||||||
|
return fs.GetPids(c)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) writeContainerFile(container *libcontainer.Container, id string) error {
|
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 {
|
func (d *driver) removeContainerRoot(id string) error {
|
||||||
|
delete(d.activeContainers, id)
|
||||||
|
|
||||||
return os.RemoveAll(filepath.Join(d.root, id))
|
return os.RemoveAll(filepath.Join(d.root, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,36 @@ func GetStats(c *cgroups.Cgroup, subsystem string, pid int) (map[string]float64,
|
||||||
return sys.Stats(d)
|
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) {
|
func (raw *data) parent(subsystem string) (string, error) {
|
||||||
initPath, err := cgroups.GetInitCgroupDir(subsystem)
|
initPath, err := cgroups.GetInitCgroupDir(subsystem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
type devicesGroup struct {
|
type devicesGroup struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,11 +8,6 @@ func (s *devicesGroup) Set(d *data) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
os.RemoveAll(dir)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if !d.c.DeviceAccess {
|
if !d.c.DeviceAccess {
|
||||||
if err := writeFile(dir, "devices.deny", "a"); err != nil {
|
if err := writeFile(dir, "devices.deny", "a"); err != nil {
|
||||||
|
|
|
@ -12,6 +12,10 @@ func UseSystemd() bool {
|
||||||
return false
|
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")
|
return nil, fmt.Errorf("Systemd not supported")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package systemd
|
package systemd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -78,7 +79,7 @@ type cgroupArg struct {
|
||||||
|
|
||||||
func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
|
func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
|
||||||
var (
|
var (
|
||||||
unitName = c.Parent + "-" + c.Name + ".scope"
|
unitName = getUnitName(c)
|
||||||
slice = "system.slice"
|
slice = "system.slice"
|
||||||
properties []systemd1.Property
|
properties []systemd1.Property
|
||||||
cpuArgs []cgroupArg
|
cpuArgs []cgroupArg
|
||||||
|
@ -303,3 +304,24 @@ func (c *systemdCgroup) Cleanup() error {
|
||||||
|
|
||||||
return nil
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/dotcloud/docker/pkg/mount"
|
"github.com/dotcloud/docker/pkg/mount"
|
||||||
|
@ -49,6 +51,30 @@ func GetInitCgroupDir(subsystem string) (string, error) {
|
||||||
return parseCgroupFile(subsystem, f)
|
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) {
|
func parseCgroupFile(subsystem string, r io.Reader) (string, error) {
|
||||||
s := bufio.NewScanner(r)
|
s := bufio.NewScanner(r)
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
|
|
Loading…
Reference in New Issue