| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"github.com/dotcloud/docker/execdriver" |
| 8 | 8 |
"github.com/dotcloud/docker/execdriver/lxc" |
| 9 |
+ "github.com/dotcloud/docker/pkg/cgroups" |
|
| 9 | 10 |
"github.com/dotcloud/docker/pkg/libcontainer" |
| 10 | 11 |
"github.com/dotcloud/docker/pkg/libcontainer/nsinit" |
| 11 | 12 |
"io" |
| ... | ... |
@@ -13,6 +14,7 @@ import ( |
| 13 | 13 |
"os" |
| 14 | 14 |
"os/exec" |
| 15 | 15 |
"path/filepath" |
| 16 |
+ "strconv" |
|
| 16 | 17 |
"strings" |
| 17 | 18 |
"syscall" |
| 18 | 19 |
) |
| ... | ... |
@@ -125,7 +127,40 @@ func (d *driver) Name() string {
|
| 125 | 125 |
} |
| 126 | 126 |
|
| 127 | 127 |
func (d *driver) GetPidsForContainer(id string) ([]int, error) {
|
| 128 |
- return nil, ErrNotSupported |
|
| 128 |
+ pids := []int{}
|
|
| 129 |
+ |
|
| 130 |
+ subsystem := "cpu" |
|
| 131 |
+ cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem) |
|
| 132 |
+ if err != nil {
|
|
| 133 |
+ return pids, err |
|
| 134 |
+ } |
|
| 135 |
+ cgroupRoot = filepath.Dir(cgroupRoot) |
|
| 136 |
+ |
|
| 137 |
+ cgroupDir, err := cgroups.GetThisCgroupDir(subsystem) |
|
| 138 |
+ if err != nil {
|
|
| 139 |
+ return pids, err |
|
| 140 |
+ } |
|
| 141 |
+ |
|
| 142 |
+ filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks") |
|
| 143 |
+ if _, err := os.Stat(filename); os.IsNotExist(err) {
|
|
| 144 |
+ filename = filepath.Join(cgroupRoot, cgroupDir, "docker", id, "tasks") |
|
| 145 |
+ } |
|
| 146 |
+ |
|
| 147 |
+ output, err := ioutil.ReadFile(filename) |
|
| 148 |
+ if err != nil {
|
|
| 149 |
+ return pids, err |
|
| 150 |
+ } |
|
| 151 |
+ for _, p := range strings.Split(string(output), "\n") {
|
|
| 152 |
+ if len(p) == 0 {
|
|
| 153 |
+ continue |
|
| 154 |
+ } |
|
| 155 |
+ pid, err := strconv.Atoi(p) |
|
| 156 |
+ if err != nil {
|
|
| 157 |
+ return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
|
|
| 158 |
+ } |
|
| 159 |
+ pids = append(pids, pid) |
|
| 160 |
+ } |
|
| 161 |
+ return pids, nil |
|
| 129 | 162 |
} |
| 130 | 163 |
|
| 131 | 164 |
func writeContainerFile(container *libcontainer.Container, rootfs string) error {
|
| ... | ... |
@@ -219,6 +254,7 @@ func createContainer(c *execdriver.Command) *libcontainer.Container {
|
| 219 | 219 |
} |
| 220 | 220 |
if c.Privileged {
|
| 221 | 221 |
container.Capabilities = nil |
| 222 |
+ container.Cgroups.DeviceAccess = true |
|
| 222 | 223 |
} |
| 223 | 224 |
if c.Resources != nil {
|
| 224 | 225 |
container.Cgroups.CpuShares = c.Resources.CpuShares |
| ... | ... |
@@ -1581,8 +1581,8 @@ func TestPrivilegedCanMknod(t *testing.T) {
|
| 1581 | 1581 |
eng := NewTestEngine(t) |
| 1582 | 1582 |
runtime := mkRuntimeFromEngine(eng, t) |
| 1583 | 1583 |
defer runtime.Nuke() |
| 1584 |
- if output, _ := runContainer(eng, runtime, []string{"-privileged", "_", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok"}, t); output != "ok\n" {
|
|
| 1585 |
- t.Fatal("Could not mknod into privileged container")
|
|
| 1584 |
+ if output, err := runContainer(eng, runtime, []string{"-privileged", "_", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok"}, t); output != "ok\n" {
|
|
| 1585 |
+ t.Fatalf("Could not mknod into privileged container %s %v", output, err)
|
|
| 1586 | 1586 |
} |
| 1587 | 1587 |
} |
| 1588 | 1588 |
|
| ... | ... |
@@ -9,7 +9,6 @@ import ( |
| 9 | 9 |
"github.com/dotcloud/docker/pkg/libcontainer/network" |
| 10 | 10 |
"github.com/dotcloud/docker/pkg/system" |
| 11 | 11 |
"github.com/dotcloud/docker/pkg/user" |
| 12 |
- "log" |
|
| 13 | 12 |
"os" |
| 14 | 13 |
"os/exec" |
| 15 | 14 |
"path/filepath" |
| ... | ... |
@@ -23,7 +22,6 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync |
| 23 | 23 |
if err != nil {
|
| 24 | 24 |
return err |
| 25 | 25 |
} |
| 26 |
- log.Printf("initializing namespace at %s", rootfs)
|
|
| 27 | 26 |
|
| 28 | 27 |
// We always read this as it is a way to sync with the parent as well |
| 29 | 28 |
context, err := syncPipe.ReadFromParent() |
| ... | ... |
@@ -32,10 +30,8 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync |
| 32 | 32 |
return err |
| 33 | 33 |
} |
| 34 | 34 |
syncPipe.Close() |
| 35 |
- log.Printf("received context from parent %v", context)
|
|
| 36 | 35 |
|
| 37 | 36 |
if console != "" {
|
| 38 |
- log.Printf("setting up console for %s", console)
|
|
| 39 | 37 |
// close pipes so that we can replace it with the pty |
| 40 | 38 |
closeStdPipes() |
| 41 | 39 |
slave, err := openTerminal(console, syscall.O_RDWR) |
| ... | ... |
@@ -66,11 +62,9 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync |
| 66 | 66 |
if err := system.Sethostname(container.Hostname); err != nil {
|
| 67 | 67 |
return fmt.Errorf("sethostname %s", err)
|
| 68 | 68 |
} |
| 69 |
- log.Printf("dropping capabilities")
|
|
| 70 | 69 |
if err := capabilities.DropCapabilities(container); err != nil {
|
| 71 | 70 |
return fmt.Errorf("drop capabilities %s", err)
|
| 72 | 71 |
} |
| 73 |
- log.Printf("setting user in namespace")
|
|
| 74 | 72 |
if err := setupUser(container); err != nil {
|
| 75 | 73 |
return fmt.Errorf("setup user %s", err)
|
| 76 | 74 |
} |
| ... | ... |
@@ -87,7 +81,6 @@ func execArgs(args []string, env []string) error {
|
| 87 | 87 |
if err != nil {
|
| 88 | 88 |
return err |
| 89 | 89 |
} |
| 90 |
- log.Printf("execing %s goodbye", name)
|
|
| 91 | 90 |
if err := system.Exec(name, args[0:], env); err != nil {
|
| 92 | 91 |
return fmt.Errorf("exec %s", err)
|
| 93 | 92 |
} |
| ... | ... |
@@ -111,7 +104,7 @@ func resolveRootfs(uncleanRootfs string) (string, error) {
|
| 111 | 111 |
} |
| 112 | 112 |
|
| 113 | 113 |
func setupUser(container *libcontainer.Container) error {
|
| 114 |
- if container.User != "" {
|
|
| 114 |
+ if container.User != "" && container.User != "root" {
|
|
| 115 | 115 |
uid, gid, suppGids, err := user.GetUserGroupSupplementary(container.User, syscall.Getuid(), syscall.Getgid()) |
| 116 | 116 |
if err != nil {
|
| 117 | 117 |
return err |