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:
parent
39fe4b4712
commit
d236be61b0
|
@ -5,17 +5,12 @@ type Container struct {
|
|||
ReadonlyFs bool `json:"readonly_fs,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
WorkingDir string `json:"working_dir,omitempty"`
|
||||
Command *Command `json:"command,omitempty"`
|
||||
Env []string `json:"environment,omitempty"`
|
||||
Namespaces Namespaces `json:"namespaces,omitempty"`
|
||||
Capabilities Capabilities `json:"capabilities,omitempty"`
|
||||
Network *Network `json:"network,omitempty"`
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
Args []string `json:"args,omitempty"`
|
||||
Env []string `json:"environment,omitempty"`
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
IP string `json:"ip,omitempty"`
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
{
|
||||
"hostname": "koye",
|
||||
"command": {
|
||||
"args": [
|
||||
"/bin/bash"
|
||||
],
|
||||
"environment": [
|
||||
"HOME=/",
|
||||
"PATH=PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin",
|
||||
"container=docker",
|
||||
"TERM=xterm-256color"
|
||||
]
|
||||
},
|
||||
],
|
||||
"namespaces": [
|
||||
"NEWIPC",
|
||||
"NEWNS",
|
||||
|
|
|
@ -16,17 +16,13 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
func execCommand(container *libcontainer.Container) (int, error) {
|
||||
func execCommand(container *libcontainer.Container, args []string) (int, error) {
|
||||
master, console, err := createMasterAndConsole()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
command := exec.Command("nsinit", "init", console)
|
||||
command.SysProcAttr = &syscall.SysProcAttr{
|
||||
Cloneflags: uintptr(getNamespaceFlags(container.Namespaces) | syscall.CLONE_VFORK), // we need CLONE_VFORK so we can wait on the child
|
||||
}
|
||||
|
||||
command := createCommand(container, console, args)
|
||||
// create a pipe so that we can syncronize with the namespaced process and
|
||||
// pass the veth name to the child
|
||||
inPipe, err := command.StdinPipe()
|
||||
|
@ -39,6 +35,7 @@ func execCommand(container *libcontainer.Container) (int, error) {
|
|||
if err := writePidFile(command); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer deletePidFile()
|
||||
|
||||
if container.Network != nil {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -5,19 +5,13 @@ import (
|
|||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer/capabilities"
|
||||
"github.com/dotcloud/docker/pkg/system"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func execinCommand(container *libcontainer.Container) (int, error) {
|
||||
nspid, err := readPid()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
func execinCommand(container *libcontainer.Container, nspid int, args []string) (int, error) {
|
||||
for _, ns := range container.Namespaces {
|
||||
if err := system.Unshare(namespaceMap[ns]); err != nil {
|
||||
return -1, err
|
||||
|
@ -67,7 +61,7 @@ func execinCommand(container *libcontainer.Container) (int, error) {
|
|||
if err := capabilities.DropCapabilities(container); err != nil {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -84,24 +78,12 @@ func execinCommand(container *libcontainer.Container) (int, error) {
|
|||
if err := capabilities.DropCapabilities(container); err != nil {
|
||||
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
|
||||
}
|
||||
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) {
|
||||
fds := make([]uintptr, len(container.Namespaces))
|
||||
for i, ns := range container.Namespaces {
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
func initCommand(container *libcontainer.Container, console string) error {
|
||||
func initCommand(container *libcontainer.Container, console string, args []string) error {
|
||||
rootfs, err := resolveRootfs()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -72,7 +72,7 @@ func initCommand(container *libcontainer.Container, console string) error {
|
|||
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)
|
||||
}
|
||||
panic("unreachable")
|
||||
|
|
|
@ -4,8 +4,10 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -25,24 +27,29 @@ func main() {
|
|||
}
|
||||
switch os.Args[1] {
|
||||
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 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
os.Exit(exitCode)
|
||||
case "init":
|
||||
if argc != 3 {
|
||||
if argc < 3 {
|
||||
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)
|
||||
}
|
||||
case "execin":
|
||||
exitCode, err := execinCommand(container)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
os.Exit(exitCode)
|
||||
default:
|
||||
log.Fatalf("command not supported for nsinit %s", os.Args[1])
|
||||
}
|
||||
|
@ -61,3 +68,15 @@ func loadContainer() (*libcontainer.Container, error) {
|
|||
}
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue