Use a custom pipe instead of stdin for sync net namespace
Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes <guillaume.charmes@docker.com> (github: creack)
This commit is contained in:
parent
3677967f4e
commit
b2e01cbe8c
3 changed files with 19 additions and 11 deletions
|
@ -22,16 +22,20 @@ func execCommand(container *libcontainer.Container, args []string) (int, error)
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
command := createCommand(container, console, args)
|
|
||||||
// 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()
|
r, w, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
system.UsetCloseOnExec(r.Fd())
|
||||||
|
|
||||||
|
command := createCommand(container, console, r.Fd(), args)
|
||||||
|
|
||||||
if err := command.Start(); err != nil {
|
if err := command.Start(); err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := writePidFile(command); err != nil {
|
if err := writePidFile(command); err != nil {
|
||||||
command.Process.Kill()
|
command.Process.Kill()
|
||||||
return -1, err
|
return -1, err
|
||||||
|
@ -52,11 +56,11 @@ func execCommand(container *libcontainer.Container, args []string) (int, error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
sendVethName(vethPair, inPipe)
|
sendVethName(vethPair, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync with child
|
// Sync with child
|
||||||
inPipe.Close()
|
w.Close()
|
||||||
|
|
||||||
go io.Copy(os.Stdout, master)
|
go io.Copy(os.Stdout, master)
|
||||||
go io.Copy(master, os.Stdin)
|
go io.Copy(master, os.Stdin)
|
||||||
|
@ -163,8 +167,8 @@ func deletePidFile() error {
|
||||||
// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
|
// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
|
||||||
// defined on the container's configuration and use the current binary as the init with the
|
// defined on the container's configuration and use the current binary as the init with the
|
||||||
// args provided
|
// args provided
|
||||||
func createCommand(container *libcontainer.Container, console string, args []string) *exec.Cmd {
|
func createCommand(container *libcontainer.Container, console string, pipe uintptr, args []string) *exec.Cmd {
|
||||||
command := exec.Command("nsinit", append([]string{"-console", console, "init"}, args...)...)
|
command := exec.Command("nsinit", append([]string{"-console", console, "-pipe", fmt.Sprint(pipe), "init"}, args...)...)
|
||||||
command.SysProcAttr = &syscall.SysProcAttr{
|
command.SysProcAttr = &syscall.SysProcAttr{
|
||||||
Cloneflags: uintptr(getNamespaceFlags(container.Namespaces)),
|
Cloneflags: uintptr(getNamespaceFlags(container.Namespaces)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,20 +8,21 @@ import (
|
||||||
"github.com/dotcloud/docker/pkg/libcontainer/capabilities"
|
"github.com/dotcloud/docker/pkg/libcontainer/capabilities"
|
||||||
"github.com/dotcloud/docker/pkg/libcontainer/network"
|
"github.com/dotcloud/docker/pkg/libcontainer/network"
|
||||||
"github.com/dotcloud/docker/pkg/system"
|
"github.com/dotcloud/docker/pkg/system"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initCommand(container *libcontainer.Container, console string, args []string) error {
|
func initCommand(container *libcontainer.Container, console string, pipe io.ReadCloser, args []string) error {
|
||||||
rootfs, err := resolveRootfs()
|
rootfs, err := resolveRootfs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We always read this as it is a way to sync with the parent as well
|
// We always read this as it is a way to sync with the parent as well
|
||||||
tempVethName, err := getVethName()
|
tempVethName, err := getVethName(pipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -164,8 +165,10 @@ func setupVethNetwork(config *libcontainer.Network, tempVethName string) error {
|
||||||
// getVethName reads from Stdin the temp veth name
|
// getVethName reads from Stdin the temp veth name
|
||||||
// sent by the parent processes after the veth pair
|
// sent by the parent processes after the veth pair
|
||||||
// has been created and setup
|
// has been created and setup
|
||||||
func getVethName() (string, error) {
|
func getVethName(pipe io.ReadCloser) (string, error) {
|
||||||
data, err := ioutil.ReadAll(os.Stdin)
|
defer pipe.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(pipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error reading from stdin %s", err)
|
return "", fmt.Errorf("error reading from stdin %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ var (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
console := flag.String("console", "", "Console (pty slave) name")
|
console := flag.String("console", "", "Console (pty slave) name")
|
||||||
|
pipeFd := flag.Int("pipe", 0, "sync pipe fd")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
container, err := loadContainer()
|
container, err := loadContainer()
|
||||||
|
@ -50,7 +51,7 @@ func main() {
|
||||||
if flag.NArg() < 2 {
|
if flag.NArg() < 2 {
|
||||||
log.Fatal(ErrWrongArguments)
|
log.Fatal(ErrWrongArguments)
|
||||||
}
|
}
|
||||||
if err := initCommand(container, *console, flag.Args()[1:]); err != nil {
|
if err := initCommand(container, *console, os.NewFile(uintptr(*pipeFd), "pipe"), flag.Args()[1:]); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue