| ... | ... |
@@ -7,6 +7,7 @@ import ( |
| 7 | 7 |
"github.com/dotcloud/docker/pkg/cgroups" |
| 8 | 8 |
"github.com/dotcloud/docker/pkg/libcontainer" |
| 9 | 9 |
"github.com/dotcloud/docker/pkg/libcontainer/nsinit" |
| 10 |
+ "github.com/dotcloud/docker/pkg/system" |
|
| 10 | 11 |
"io/ioutil" |
| 11 | 12 |
"os" |
| 12 | 13 |
"os/exec" |
| ... | ... |
@@ -215,9 +216,11 @@ func (d *dockerCommandFactory) Create(container *libcontainer.Container, console |
| 215 | 215 |
"-pipe", fmt.Sprint(syncFd), |
| 216 | 216 |
"-root", filepath.Join(d.driver.root, d.c.ID), |
| 217 | 217 |
}, args...) |
| 218 |
- d.c.SysProcAttr = &syscall.SysProcAttr{
|
|
| 219 |
- Cloneflags: uintptr(nsinit.GetNamespaceFlags(container.Namespaces)), |
|
| 220 |
- } |
|
| 218 |
+ |
|
| 219 |
+ // set this to nil so that when we set the clone flags anything else is reset |
|
| 220 |
+ d.c.SysProcAttr = nil |
|
| 221 |
+ system.SetCloneFlags(&d.c.Cmd, uintptr(nsinit.GetNamespaceFlags(container.Namespaces))) |
|
| 222 |
+ |
|
| 221 | 223 |
d.c.Env = container.Env |
| 222 | 224 |
d.c.Dir = d.c.Rootfs |
| 223 | 225 |
|
| ... | ... |
@@ -3,9 +3,9 @@ package nsinit |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"github.com/dotcloud/docker/pkg/libcontainer" |
| 6 |
+ "github.com/dotcloud/docker/pkg/system" |
|
| 6 | 7 |
"os" |
| 7 | 8 |
"os/exec" |
| 8 |
- "syscall" |
|
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// CommandFactory takes the container's configuration and options passed by the |
| ... | ... |
@@ -15,22 +15,31 @@ type CommandFactory interface {
|
| 15 | 15 |
Create(container *libcontainer.Container, console string, syncFd uintptr, args []string) *exec.Cmd |
| 16 | 16 |
} |
| 17 | 17 |
|
| 18 |
-type DefaultCommandFactory struct{}
|
|
| 18 |
+type DefaultCommandFactory struct {
|
|
| 19 |
+ Root string |
|
| 20 |
+} |
|
| 19 | 21 |
|
| 20 | 22 |
// Create will return an exec.Cmd with the Cloneflags set to the proper namespaces |
| 21 | 23 |
// defined on the container's configuration and use the current binary as the init with the |
| 22 | 24 |
// args provided |
| 23 | 25 |
func (c *DefaultCommandFactory) Create(container *libcontainer.Container, console string, pipe uintptr, args []string) *exec.Cmd {
|
| 24 |
- // get our binary name so we can always reexec ourself |
|
| 25 |
- name := os.Args[0] |
|
| 26 |
- command := exec.Command(name, append([]string{
|
|
| 26 |
+ // get our binary name from arg0 so we can always reexec ourself |
|
| 27 |
+ command := exec.Command(os.Args[0], append([]string{
|
|
| 27 | 28 |
"-console", console, |
| 28 | 29 |
"-pipe", fmt.Sprint(pipe), |
| 30 |
+ "-root", c.Root, |
|
| 29 | 31 |
"init"}, args...)...) |
| 30 | 32 |
|
| 31 |
- command.SysProcAttr = &syscall.SysProcAttr{
|
|
| 32 |
- Cloneflags: uintptr(GetNamespaceFlags(container.Namespaces)), |
|
| 33 |
- } |
|
| 33 |
+ system.SetCloneFlags(command, uintptr(GetNamespaceFlags(container.Namespaces))) |
|
| 34 | 34 |
command.Env = container.Env |
| 35 | 35 |
return command |
| 36 | 36 |
} |
| 37 |
+ |
|
| 38 |
+// GetNamespaceFlags parses the container's Namespaces options to set the correct |
|
| 39 |
+// flags on clone, unshare, and setns |
|
| 40 |
+func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
|
| 41 |
+ for _, ns := range namespaces {
|
|
| 42 |
+ flag |= ns.Value |
|
| 43 |
+ } |
|
| 44 |
+ return flag |
|
| 45 |
+} |
| 4 | 6 |
deleted file mode 100644 |
| ... | ... |
@@ -1,14 +0,0 @@ |
| 1 |
-package nsinit |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "github.com/dotcloud/docker/pkg/libcontainer" |
|
| 5 |
-) |
|
| 6 |
- |
|
| 7 |
-// getNamespaceFlags parses the container's Namespaces options to set the correct |
|
| 8 |
-// flags on clone, unshare, and setns |
|
| 9 |
-func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
|
| 10 |
- for _, ns := range namespaces {
|
|
| 11 |
- flag |= ns.Value |
|
| 12 |
- } |
|
| 13 |
- return flag |
|
| 14 |
-} |
| ... | ... |
@@ -2,7 +2,6 @@ package main |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 |
- "errors" |
|
| 6 | 5 |
"flag" |
| 7 | 6 |
"github.com/dotcloud/docker/pkg/libcontainer" |
| 8 | 7 |
"github.com/dotcloud/docker/pkg/libcontainer/nsinit" |
| ... | ... |
@@ -18,11 +17,6 @@ var ( |
| 18 | 18 |
pipeFd int |
| 19 | 19 |
) |
| 20 | 20 |
|
| 21 |
-var ( |
|
| 22 |
- ErrUnsupported = errors.New("Unsupported method")
|
|
| 23 |
- ErrWrongArguments = errors.New("Wrong argument count")
|
|
| 24 |
-) |
|
| 25 |
- |
|
| 26 | 21 |
func registerFlags() {
|
| 27 | 22 |
flag.StringVar(&console, "console", "", "console (pty slave) path") |
| 28 | 23 |
flag.IntVar(&pipeFd, "pipe", 0, "sync pipe fd") |
| ... | ... |
@@ -35,7 +29,7 @@ func main() {
|
| 35 | 35 |
registerFlags() |
| 36 | 36 |
|
| 37 | 37 |
if flag.NArg() < 1 {
|
| 38 |
- log.Fatal(ErrWrongArguments) |
|
| 38 |
+ log.Fatalf("wrong number of argments %d", flag.NArg())
|
|
| 39 | 39 |
} |
| 40 | 40 |
container, err := loadContainer() |
| 41 | 41 |
if err != nil {
|
| ... | ... |
@@ -71,7 +65,7 @@ func main() {
|
| 71 | 71 |
log.Fatal(err) |
| 72 | 72 |
} |
| 73 | 73 |
if flag.NArg() < 2 {
|
| 74 |
- log.Fatal(ErrWrongArguments) |
|
| 74 |
+ log.Fatalf("wrong number of argments %d", flag.NArg())
|
|
| 75 | 75 |
} |
| 76 | 76 |
syncPipe, err := nsinit.NewSyncPipeFromFd(0, uintptr(pipeFd)) |
| 77 | 77 |
if err != nil {
|
| ... | ... |
@@ -112,5 +106,5 @@ func readPid() (int, error) {
|
| 112 | 112 |
} |
| 113 | 113 |
|
| 114 | 114 |
func newNsInit() (nsinit.NsInit, error) {
|
| 115 |
- return nsinit.NewNsInit(&nsinit.DefaultCommandFactory{}, &nsinit.DefaultStateWriter{root}), nil
|
|
| 115 |
+ return nsinit.NewNsInit(&nsinit.DefaultCommandFactory{root}, &nsinit.DefaultStateWriter{root}), nil
|
|
| 116 | 116 |
} |
| 117 | 117 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,19 @@ |
| 0 |
+// +build !linux |
|
| 1 |
+ |
|
| 2 |
+package nsinit |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "github.com/dotcloud/docker/pkg/libcontainer" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+func (ns *linuxNs) Exec(container *libcontainer.Container, term Terminal, args []string) (int, error) {
|
|
| 9 |
+ return -1, libcontainer.ErrUnsupported |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 12 |
+func (ns *linuxNs) ExecIn(container *libcontainer.Container, nspid int, args []string) (int, error) {
|
|
| 13 |
+ return -1, libcontainer.ErrUnsupported |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 16 |
+func (ns *linuxNs) Init(container *libcontainer.Container, uncleanRootfs, console string, syncPipe *SyncPipe, args []string) error {
|
|
| 17 |
+ return libcontainer.ErrUnsupported |
|
| 18 |
+} |
| ... | ... |
@@ -5,25 +5,20 @@ import ( |
| 5 | 5 |
"errors" |
| 6 | 6 |
"github.com/syndtr/gocapability/capability" |
| 7 | 7 |
"os" |
| 8 |
- "syscall" |
|
| 9 | 8 |
) |
| 10 | 9 |
|
| 11 | 10 |
var ( |
| 12 |
- ErrUnkownNamespace error = errors.New("Unkown namespace")
|
|
| 11 |
+ ErrUnkownNamespace = errors.New("Unknown namespace")
|
|
| 12 |
+ ErrUnkownCapability = errors.New("Unknown capability")
|
|
| 13 |
+ ErrUnsupported = errors.New("Unsupported method")
|
|
| 13 | 14 |
) |
| 14 | 15 |
|
| 15 | 16 |
// namespaceList is used to convert the libcontainer types |
| 16 | 17 |
// into the names of the files located in /proc/<pid>/ns/* for |
| 17 | 18 |
// each namespace |
| 18 | 19 |
var ( |
| 19 |
- namespaceList = Namespaces{
|
|
| 20 |
- {Key: "NEWNS", Value: syscall.CLONE_NEWNS, File: "mnt"},
|
|
| 21 |
- {Key: "NEWUTS", Value: syscall.CLONE_NEWUTS, File: "uts"},
|
|
| 22 |
- {Key: "NEWIPC", Value: syscall.CLONE_NEWIPC, File: "ipc"},
|
|
| 23 |
- {Key: "NEWUSER", Value: syscall.CLONE_NEWUSER, File: "user"},
|
|
| 24 |
- {Key: "NEWPID", Value: syscall.CLONE_NEWPID, File: "pid"},
|
|
| 25 |
- {Key: "NEWNET", Value: syscall.CLONE_NEWNET, File: "net"},
|
|
| 26 |
- } |
|
| 20 |
+ namespaceList = Namespaces{}
|
|
| 21 |
+ |
|
| 27 | 22 |
capabilityList = Capabilities{
|
| 28 | 23 |
{Key: "SETPCAP", Value: capability.CAP_SETPCAP},
|
| 29 | 24 |
{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE},
|
| ... | ... |
@@ -52,6 +47,10 @@ type ( |
| 52 | 52 |
Namespaces []*Namespace |
| 53 | 53 |
) |
| 54 | 54 |
|
| 55 |
+func (ns *Namespace) String() string {
|
|
| 56 |
+ return ns.Key |
|
| 57 |
+} |
|
| 58 |
+ |
|
| 55 | 59 |
func (ns *Namespace) MarshalJSON() ([]byte, error) {
|
| 56 | 60 |
return json.Marshal(ns.Key) |
| 57 | 61 |
} |
| ... | ... |
@@ -95,20 +94,24 @@ type ( |
| 95 | 95 |
Capabilities []*Capability |
| 96 | 96 |
) |
| 97 | 97 |
|
| 98 |
-func (ns *Capability) MarshalJSON() ([]byte, error) {
|
|
| 99 |
- return json.Marshal(ns.Key) |
|
| 98 |
+func (c *Capability) String() string {
|
|
| 99 |
+ return c.Key |
|
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 |
-func (ns *Capability) UnmarshalJSON(src []byte) error {
|
|
| 102 |
+func (c *Capability) MarshalJSON() ([]byte, error) {
|
|
| 103 |
+ return json.Marshal(c.Key) |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 106 |
+func (c *Capability) UnmarshalJSON(src []byte) error {
|
|
| 103 | 107 |
var capName string |
| 104 | 108 |
if err := json.Unmarshal(src, &capName); err != nil {
|
| 105 | 109 |
return err |
| 106 | 110 |
} |
| 107 | 111 |
ret := GetCapability(capName) |
| 108 | 112 |
if ret == nil {
|
| 109 |
- return ErrUnkownNamespace |
|
| 113 |
+ return ErrUnkownCapability |
|
| 110 | 114 |
} |
| 111 |
- *ns = *ret |
|
| 115 |
+ *c = *ret |
|
| 112 | 116 |
return nil |
| 113 | 117 |
} |
| 114 | 118 |
|
| ... | ... |
@@ -119,7 +122,7 @@ func GetCapability(key string) *Capability {
|
| 119 | 119 |
} |
| 120 | 120 |
} |
| 121 | 121 |
if os.Getenv("DEBUG") != "" {
|
| 122 |
- panic("Unreachable: Namespace not found")
|
|
| 122 |
+ panic("Unreachable: Capability not found")
|
|
| 123 | 123 |
} |
| 124 | 124 |
return nil |
| 125 | 125 |
} |
| 126 | 126 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 0 |
+package libcontainer |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "syscall" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+func init() {
|
|
| 7 |
+ namespaceList = Namespaces{
|
|
| 8 |
+ {Key: "NEWNS", Value: syscall.CLONE_NEWNS, File: "mnt"},
|
|
| 9 |
+ {Key: "NEWUTS", Value: syscall.CLONE_NEWUTS, File: "uts"},
|
|
| 10 |
+ {Key: "NEWIPC", Value: syscall.CLONE_NEWIPC, File: "ipc"},
|
|
| 11 |
+ {Key: "NEWUSER", Value: syscall.CLONE_NEWUSER, File: "user"},
|
|
| 12 |
+ {Key: "NEWPID", Value: syscall.CLONE_NEWPID, File: "pid"},
|
|
| 13 |
+ {Key: "NEWNET", Value: syscall.CLONE_NEWNET, File: "net"},
|
|
| 14 |
+ } |
|
| 15 |
+} |
| ... | ... |
@@ -136,3 +136,10 @@ func Mkfifo(name string, mode uint32) error {
|
| 136 | 136 |
func Umask(mask int) int {
|
| 137 | 137 |
return syscall.Umask(mask) |
| 138 | 138 |
} |
| 139 |
+ |
|
| 140 |
+func SetCloneFlags(cmd *exec.Cmd, flag uintptr) {
|
|
| 141 |
+ if cmd.SysProcAttr == nil {
|
|
| 142 |
+ cmd.SysProcAttr = &syscall.SysProcAttr{}
|
|
| 143 |
+ } |
|
| 144 |
+ cmd.SysProcAttr.Cloneflags = flag |
|
| 145 |
+} |
| ... | ... |
@@ -1,16 +1,11 @@ |
| 1 | 1 |
package system |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "errors" |
|
| 5 | 4 |
"fmt" |
| 6 | 5 |
"runtime" |
| 7 | 6 |
"syscall" |
| 8 | 7 |
) |
| 9 | 8 |
|
| 10 |
-var ( |
|
| 11 |
- ErrNotSupportedPlatform = errors.New("platform and architecture is not supported")
|
|
| 12 |
-) |
|
| 13 |
- |
|
| 14 | 9 |
// Via http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7b21fddd087678a70ad64afc0f632e0f1071b092 |
| 15 | 10 |
// |
| 16 | 11 |
// We need different setns values for the different platforms and arch |
| ... | ... |
@@ -709,9 +709,12 @@ func NewRuntimeFromDirectory(config *DaemonConfig, eng *engine.Engine) (*Runtime |
| 709 | 709 |
|
| 710 | 710 |
switch config.ExecDriver {
|
| 711 | 711 |
case "lxc": |
| 712 |
+ // we want to five the lxc driver the full docker root because it needs |
|
| 713 |
+ // to access and write config and template files in /var/lib/docker/containers/* |
|
| 714 |
+ // to be backwards compatible |
|
| 712 | 715 |
ed, err = lxc.NewDriver(config.Root, sysInfo.AppArmor) |
| 713 | 716 |
case "native": |
| 714 |
- ed, err = native.NewDriver(path.Join(config.Root, "native")) |
|
| 717 |
+ ed, err = native.NewDriver(path.Join(config.Root, "execdriver", "native")) |
|
| 715 | 718 |
default: |
| 716 | 719 |
return nil, fmt.Errorf("unknown exec driver %s", config.ExecDriver)
|
| 717 | 720 |
} |