Refactor to remove cmd from container

Pass the container's command via args
Remove execin function and just look for an
existing nspid file to join the namespace
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
Michael Crosby 2014-02-19 20:35:04 -08:00
parent 39fe4b4712
commit d236be61b0
6 changed files with 55 additions and 55 deletions

View File

@ -5,17 +5,12 @@ type Container struct {
ReadonlyFs bool `json:"readonly_fs,omitempty"` ReadonlyFs bool `json:"readonly_fs,omitempty"`
User string `json:"user,omitempty"` User string `json:"user,omitempty"`
WorkingDir string `json:"working_dir,omitempty"` WorkingDir string `json:"working_dir,omitempty"`
Command *Command `json:"command,omitempty"` Env []string `json:"environment,omitempty"`
Namespaces Namespaces `json:"namespaces,omitempty"` Namespaces Namespaces `json:"namespaces,omitempty"`
Capabilities Capabilities `json:"capabilities,omitempty"` Capabilities Capabilities `json:"capabilities,omitempty"`
Network *Network `json:"network,omitempty"` Network *Network `json:"network,omitempty"`
} }
type Command struct {
Args []string `json:"args,omitempty"`
Env []string `json:"environment,omitempty"`
}
type Network struct { type Network struct {
IP string `json:"ip,omitempty"` IP string `json:"ip,omitempty"`
Gateway string `json:"gateway,omitempty"` Gateway string `json:"gateway,omitempty"`

View File

@ -1,16 +1,11 @@
{ {
"hostname": "koye", "hostname": "koye",
"command": { "environment": [
"args": [ "HOME=/",
"/bin/bash" "PATH=PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin",
], "container=docker",
"environment": [ "TERM=xterm-256color"
"HOME=/", ],
"PATH=PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin",
"container=docker",
"TERM=xterm-256color"
]
},
"namespaces": [ "namespaces": [
"NEWIPC", "NEWIPC",
"NEWNS", "NEWNS",

View File

@ -16,17 +16,13 @@ import (
"syscall" "syscall"
) )
func execCommand(container *libcontainer.Container) (int, error) { func execCommand(container *libcontainer.Container, args []string) (int, error) {
master, console, err := createMasterAndConsole() master, console, err := createMasterAndConsole()
if err != nil { if err != nil {
return -1, err return -1, err
} }
command := exec.Command("nsinit", "init", console) command := createCommand(container, console, args)
command.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: uintptr(getNamespaceFlags(container.Namespaces) | syscall.CLONE_VFORK), // we need CLONE_VFORK so we can wait on the child
}
// create a pipe so that we can syncronize with the namespaced process and // create a pipe so that we can syncronize with the namespaced process and
// pass the veth name to the child // pass the veth name to the child
inPipe, err := command.StdinPipe() inPipe, err := command.StdinPipe()
@ -39,6 +35,7 @@ func execCommand(container *libcontainer.Container) (int, error) {
if err := writePidFile(command); err != nil { if err := writePidFile(command); err != nil {
return -1, err return -1, err
} }
defer deletePidFile()
if container.Network != nil { if container.Network != nil {
vethPair, err := setupVeth(container.Network.Bridge, command.Process.Pid) vethPair, err := setupVeth(container.Network.Bridge, command.Process.Pid)
@ -134,3 +131,15 @@ func createVethPair() (name1 string, name2 string, err error) {
func writePidFile(command *exec.Cmd) error { func writePidFile(command *exec.Cmd) error {
return ioutil.WriteFile(".nspid", []byte(fmt.Sprint(command.Process.Pid)), 0655) return ioutil.WriteFile(".nspid", []byte(fmt.Sprint(command.Process.Pid)), 0655)
} }
func deletePidFile() error {
return os.Remove(".nspid")
}
func createCommand(container *libcontainer.Container, console string, args []string) *exec.Cmd {
command := exec.Command("nsinit", append([]string{"init", console}, args...)...)
command.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: uintptr(getNamespaceFlags(container.Namespaces) | syscall.CLONE_VFORK), // we need CLONE_VFORK so we can wait on the child
}
return command
}

View File

@ -5,19 +5,13 @@ import (
"github.com/dotcloud/docker/pkg/libcontainer" "github.com/dotcloud/docker/pkg/libcontainer"
"github.com/dotcloud/docker/pkg/libcontainer/capabilities" "github.com/dotcloud/docker/pkg/libcontainer/capabilities"
"github.com/dotcloud/docker/pkg/system" "github.com/dotcloud/docker/pkg/system"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
"syscall" "syscall"
) )
func execinCommand(container *libcontainer.Container) (int, error) { func execinCommand(container *libcontainer.Container, nspid int, args []string) (int, error) {
nspid, err := readPid()
if err != nil {
return -1, err
}
for _, ns := range container.Namespaces { for _, ns := range container.Namespaces {
if err := system.Unshare(namespaceMap[ns]); err != nil { if err := system.Unshare(namespaceMap[ns]); err != nil {
return -1, err return -1, err
@ -67,7 +61,7 @@ func execinCommand(container *libcontainer.Container) (int, error) {
if err := capabilities.DropCapabilities(container); err != nil { if err := capabilities.DropCapabilities(container); err != nil {
return -1, fmt.Errorf("drop capabilities %s", err) return -1, fmt.Errorf("drop capabilities %s", err)
} }
if err := system.Exec(container.Command.Args[0], container.Command.Args[0:], container.Command.Env); err != nil { if err := system.Exec(args[0], args[0:], container.Env); err != nil {
return -1, err return -1, err
} }
} }
@ -84,24 +78,12 @@ func execinCommand(container *libcontainer.Container) (int, error) {
if err := capabilities.DropCapabilities(container); err != nil { if err := capabilities.DropCapabilities(container); err != nil {
return -1, fmt.Errorf("drop capabilities %s", err) return -1, fmt.Errorf("drop capabilities %s", err)
} }
if err := system.Exec(container.Command.Args[0], container.Command.Args[0:], container.Command.Env); err != nil { if err := system.Exec(args[0], args[0:], container.Env); err != nil {
return -1, err return -1, err
} }
panic("unreachable") panic("unreachable")
} }
func readPid() (int, error) {
data, err := ioutil.ReadFile(".nspid")
if err != nil {
return -1, err
}
pid, err := strconv.Atoi(string(data))
if err != nil {
return -1, err
}
return pid, nil
}
func getNsFds(pid int, container *libcontainer.Container) ([]uintptr, error) { func getNsFds(pid int, container *libcontainer.Container) ([]uintptr, error) {
fds := make([]uintptr, len(container.Namespaces)) fds := make([]uintptr, len(container.Namespaces))
for i, ns := range container.Namespaces { for i, ns := range container.Namespaces {

View File

@ -14,7 +14,7 @@ import (
"syscall" "syscall"
) )
func initCommand(container *libcontainer.Container, console string) error { func initCommand(container *libcontainer.Container, console string, args []string) error {
rootfs, err := resolveRootfs() rootfs, err := resolveRootfs()
if err != nil { if err != nil {
return err return err
@ -72,7 +72,7 @@ func initCommand(container *libcontainer.Container, console string) error {
return fmt.Errorf("chdir to %s %s", container.WorkingDir, err) return fmt.Errorf("chdir to %s %s", container.WorkingDir, err)
} }
} }
if err := system.Exec(container.Command.Args[0], container.Command.Args[0:], container.Command.Env); err != nil { if err := system.Exec(args[0], args[0:], container.Env); err != nil {
return fmt.Errorf("exec %s", err) return fmt.Errorf("exec %s", err)
} }
panic("unreachable") panic("unreachable")

View File

@ -4,8 +4,10 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"github.com/dotcloud/docker/pkg/libcontainer" "github.com/dotcloud/docker/pkg/libcontainer"
"io/ioutil"
"log" "log"
"os" "os"
"strconv"
) )
var ( var (
@ -25,24 +27,29 @@ func main() {
} }
switch os.Args[1] { switch os.Args[1] {
case "exec": case "exec":
exitCode, err := execCommand(container) var exitCode int
nspid, err := readPid()
if err != nil {
if !os.IsNotExist(err) {
log.Fatal(err)
}
}
if nspid > 0 {
exitCode, err = execinCommand(container, nspid, os.Args[2:])
} else {
exitCode, err = execCommand(container, os.Args[2:])
}
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
os.Exit(exitCode) os.Exit(exitCode)
case "init": case "init":
if argc != 3 { if argc < 3 {
log.Fatal(ErrWrongArguments) log.Fatal(ErrWrongArguments)
} }
if err := initCommand(container, os.Args[2]); err != nil { if err := initCommand(container, os.Args[2], os.Args[3:]); err != nil {
log.Fatal(err) log.Fatal(err)
} }
case "execin":
exitCode, err := execinCommand(container)
if err != nil {
log.Fatal(err)
}
os.Exit(exitCode)
default: default:
log.Fatalf("command not supported for nsinit %s", os.Args[1]) log.Fatalf("command not supported for nsinit %s", os.Args[1])
} }
@ -61,3 +68,15 @@ func loadContainer() (*libcontainer.Container, error) {
} }
return container, nil return container, nil
} }
func readPid() (int, error) {
data, err := ioutil.ReadFile(".nspid")
if err != nil {
return -1, err
}
pid, err := strconv.Atoi(string(data))
if err != nil {
return -1, err
}
return pid, nil
}