Simplify namespaces with only nsinit
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
parent
c1f8606d50
commit
e25ebdd06c
6 changed files with 23 additions and 278 deletions
|
@ -1,203 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer/namespaces"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer/namespaces/nsinit"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer/network"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer/utils"
|
||||
"os"
|
||||
exec_ "os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
displayPid bool
|
||||
newCommand string
|
||||
usrNet bool
|
||||
masterFd int
|
||||
console string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&displayPid, "pid", false, "display the pid before waiting")
|
||||
flag.StringVar(&newCommand, "cmd", "/bin/bash", "command to run in the existing namespace")
|
||||
flag.BoolVar(&usrNet, "net", false, "user a net namespace")
|
||||
flag.IntVar(&masterFd, "master", 0, "master fd")
|
||||
flag.StringVar(&console, "console", "", "console path")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func nsinitFunc(container *libcontainer.Container) error {
|
||||
container.Master = uintptr(masterFd)
|
||||
container.Console = console
|
||||
container.LogFile = "/root/logs"
|
||||
|
||||
return nsinit.InitNamespace(container)
|
||||
}
|
||||
|
||||
func exec(container *libcontainer.Container) error {
|
||||
var (
|
||||
netFile *os.File
|
||||
err error
|
||||
)
|
||||
container.NetNsFd = 0
|
||||
|
||||
if usrNet {
|
||||
netFile, err = os.Open("/root/nsroot/test")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
container.NetNsFd = netFile.Fd()
|
||||
}
|
||||
|
||||
self, err := exec_.LookPath(os.Args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if output, err := exec_.Command("cp", self, path.Join(container.RootFs, ".nsinit")).CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("Error exec cp: %s, (%s)", err, output)
|
||||
} else {
|
||||
println(self, container.RootFs)
|
||||
fmt.Printf("-----> %s\n", output)
|
||||
}
|
||||
println("----")
|
||||
|
||||
pid, err := namespaces.ExecContainer(container)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error exec container %s", err)
|
||||
}
|
||||
|
||||
if displayPid {
|
||||
fmt.Println(pid)
|
||||
}
|
||||
|
||||
exitcode, err := utils.WaitOnPid(pid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error waiting on child %s", err)
|
||||
}
|
||||
fmt.Println(exitcode)
|
||||
if usrNet {
|
||||
netFile.Close()
|
||||
if err := network.DeleteNetworkNamespace("/root/nsroot/test"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
os.Exit(exitcode)
|
||||
return nil
|
||||
}
|
||||
|
||||
func execIn(container *libcontainer.Container) error {
|
||||
// f, err := os.Open("/root/nsroot/test")
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// container.NetNsFd = f.Fd()
|
||||
// pid, err := namespaces.ExecIn(container, &libcontainer.Command{
|
||||
// Env: container.Command.Env,
|
||||
// Args: []string{
|
||||
// newCommand,
|
||||
// },
|
||||
// })
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("error exexin container %s", err)
|
||||
// }
|
||||
// exitcode, err := utils.WaitOnPid(pid)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("error waiting on child %s", err)
|
||||
// }
|
||||
// os.Exit(exitcode)
|
||||
return nil
|
||||
}
|
||||
|
||||
func createNet(config *libcontainer.Network) error {
|
||||
/*
|
||||
root := "/root/nsroot"
|
||||
if err := network.SetupNamespaceMountDir(root); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nspath := root + "/test"
|
||||
if err := network.CreateNetworkNamespace(nspath); err != nil {
|
||||
return nil
|
||||
}
|
||||
if err := network.CreateVethPair("veth0", config.TempVethName); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := network.SetInterfaceMaster("veth0", config.Bridge); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := network.InterfaceUp("veth0"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.Open(nspath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := network.SetInterfaceInNamespaceFd("veth1", int(f.Fd())); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := network.SetupVethInsideNamespace(f.Fd(), config); err != nil {
|
||||
return err
|
||||
}
|
||||
*/
|
||||
return nil
|
||||
}
|
||||
|
||||
func printErr(err error) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
cliCmd := flag.Arg(0)
|
||||
|
||||
config, err := filepath.Abs(flag.Arg(1))
|
||||
if err != nil {
|
||||
printErr(err)
|
||||
}
|
||||
println("cli:", cliCmd, "config:", config)
|
||||
f, err := os.Open(config)
|
||||
if err != nil {
|
||||
printErr(err)
|
||||
}
|
||||
|
||||
dec := json.NewDecoder(f)
|
||||
var container *libcontainer.Container
|
||||
|
||||
if err := dec.Decode(&container); err != nil {
|
||||
printErr(err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
switch cliCmd {
|
||||
case "init":
|
||||
err = nsinitFunc(container)
|
||||
case "exec":
|
||||
err = exec(container)
|
||||
case "execin":
|
||||
err = execIn(container)
|
||||
case "net":
|
||||
err = createNet(&libcontainer.Network{
|
||||
TempVethName: "veth1",
|
||||
IP: "172.17.0.100/16",
|
||||
Gateway: "172.17.42.1",
|
||||
Mtu: 1500,
|
||||
Bridge: "docker0",
|
||||
})
|
||||
default:
|
||||
err = fmt.Errorf("command not supported: %s", cliCmd)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
printErr(err)
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package namespaces
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func addEnvIfNotSet(container *libcontainer.Container, key, value string) {
|
||||
jv := fmt.Sprintf("%s=%s", key, value)
|
||||
if len(container.Command.Env) == 0 {
|
||||
container.Command.Env = []string{jv}
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range container.Command.Env {
|
||||
parts := strings.Split(v, "=")
|
||||
if parts[0] == key {
|
||||
return
|
||||
}
|
||||
}
|
||||
container.Command.Env = append(container.Command.Env, jv)
|
||||
}
|
||||
|
||||
// getNsFd returns the fd for a specific pid and namespace option
|
||||
func getNsFd(pid int, ns string) (uintptr, error) {
|
||||
nspath := filepath.Join("/proc", strconv.Itoa(pid), "ns", ns)
|
||||
// OpenFile adds closOnExec
|
||||
f, err := os.OpenFile(nspath, os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f.Fd(), nil
|
||||
}
|
||||
|
||||
// setupEnvironment adds additional environment variables to the container's
|
||||
// Command such as USER, LOGNAME, container, and TERM
|
||||
func setupEnvironment(container *libcontainer.Container) {
|
||||
addEnvIfNotSet(container, "container", "docker")
|
||||
// TODO: check if pty
|
||||
addEnvIfNotSet(container, "TERM", "xterm")
|
||||
// TODO: get username from container
|
||||
addEnvIfNotSet(container, "USER", "root")
|
||||
addEnvIfNotSet(container, "LOGNAME", "root")
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package namespaces
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
|
@ -11,15 +11,7 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
// ExecContainer will spawn new namespaces with the specified Container configuration
|
||||
// in the RootFs path and return the pid of the new containerized process.
|
||||
//
|
||||
// If an existing network namespace is specified the container
|
||||
// will join that namespace. If an existing network namespace is not specified but CLONE_NEWNET is,
|
||||
// the container will be spawned with a new network namespace with no configuration. Omiting an
|
||||
// existing network namespace and the CLONE_NEWNET option in the container configuration will allow
|
||||
// the container to the the host's networking options and configuration.
|
||||
func ExecContainer(container *libcontainer.Container) (pid int, err error) {
|
||||
func execCommand(container *libcontainer.Container) (pid int, err error) {
|
||||
master, console, err := createMasterAndConsole()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
|
@ -50,7 +42,19 @@ func ExecContainer(container *libcontainer.Container) (pid int, err error) {
|
|||
}
|
||||
}()
|
||||
|
||||
term.SetRawTerminal(os.Stdin.Fd())
|
||||
ws, err := term.GetWinsize(os.Stdin.Fd())
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
if err := term.SetWinsize(master.Fd(), ws); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
state, err := term.SetRawTerminal(os.Stdin.Fd())
|
||||
if err != nil {
|
||||
command.Process.Kill()
|
||||
return -1, err
|
||||
}
|
||||
defer term.RestoreTerminal(os.Stdin.Fd(), state)
|
||||
|
||||
if err := command.Wait(); err != nil {
|
||||
return pid, err
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer/capabilities"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer/namespaces"
|
||||
"github.com/dotcloud/docker/pkg/system"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -34,7 +33,7 @@ func main() {
|
|||
}
|
||||
|
||||
if os.Args[1] == "exec" {
|
||||
_, err := namespaces.ExecContainer(container)
|
||||
_, err := execCommand(container)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -157,11 +156,13 @@ func openTerminal(name string, flag int) (*os.File, error) {
|
|||
}
|
||||
|
||||
func setLogFile(container *libcontainer.Container) error {
|
||||
if container.LogFile != "" {
|
||||
f, err := os.OpenFile(container.LogFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0655)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.SetOutput(f)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package namespaces
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
|
@ -25,15 +25,6 @@ var namespaceMap = map[libcontainer.Namespace]int{
|
|||
libcontainer.CLONE_NEWNET: CLONE_NEWNET,
|
||||
}
|
||||
|
||||
var namespaceFileMap = map[libcontainer.Namespace]string{
|
||||
libcontainer.CLONE_NEWNS: "mnt",
|
||||
libcontainer.CLONE_NEWUTS: "uts",
|
||||
libcontainer.CLONE_NEWIPC: "ipc",
|
||||
libcontainer.CLONE_NEWUSER: "user",
|
||||
libcontainer.CLONE_NEWPID: "pid",
|
||||
libcontainer.CLONE_NEWNET: "net",
|
||||
}
|
||||
|
||||
// getNamespaceFlags parses the container's Namespaces options to set the correct
|
||||
// flags on clone, unshare, and setns
|
||||
func getNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
Loading…
Reference in a new issue