Browse code

Make nsinit a proper go pkg and add the main in another dir Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/02/21 11:27:42
Showing 8 changed files
... ...
@@ -72,9 +72,11 @@ rootfs and copy a `container.json` file into the directory with your specified c
72 72
 
73 73
 To execution `/bin/bash` in the current directory as a container just run:
74 74
 ```bash
75
-nsinit exec /bin/bash
75
+nsinit -tty exec /bin/bash
76 76
 ```
77 77
 
78
+If you want a proper tty setup inside the new container you must use the `-tty` flag when running nsinit.
79
+
78 80
 If you wish to spawn another process inside the container while your current bash session is 
79 81
 running just run the exact same command again to get another bash shell or change the command.  If the original process dies, PID 1, all other processes spawned inside the container will also be killed and the namespace will be removed. 
80 82
 
... ...
@@ -1,6 +1,6 @@
1 1
 // +build linux
2 2
 
3
-package main
3
+package nsinit
4 4
 
5 5
 import (
6 6
 	"fmt"
... ...
@@ -16,7 +16,9 @@ import (
16 16
 	"syscall"
17 17
 )
18 18
 
19
-func execCommand(container *libcontainer.Container, tty bool, args []string) (int, error) {
19
+// Exec performes setup outside of a namespace so that a container can be
20
+// executed.  Exec is a high level function for working with container namespaces.
21
+func Exec(container *libcontainer.Container, tty bool, args []string) (int, error) {
20 22
 	var (
21 23
 		master  *os.File
22 24
 		console string
... ...
@@ -1,4 +1,4 @@
1
-package main
1
+package nsinit
2 2
 
3 3
 import (
4 4
 	"fmt"
... ...
@@ -11,7 +11,8 @@ import (
11 11
 	"syscall"
12 12
 )
13 13
 
14
-func execinCommand(container *libcontainer.Container, nspid int, args []string) (int, error) {
14
+// ExecIn uses an existing pid and joins the pid's namespaces with the new command.
15
+func ExecIn(container *libcontainer.Container, nspid int, args []string) (int, error) {
15 16
 	for _, ns := range container.Namespaces {
16 17
 		if err := system.Unshare(namespaceMap[ns]); err != nil {
17 18
 			return -1, err
... ...
@@ -1,6 +1,6 @@
1 1
 // +build linux
2 2
 
3
-package main
3
+package nsinit
4 4
 
5 5
 import (
6 6
 	"fmt"
... ...
@@ -15,7 +15,9 @@ import (
15 15
 	"syscall"
16 16
 )
17 17
 
18
-func initCommand(container *libcontainer.Container, console string, pipe io.ReadCloser, args []string) error {
18
+// Init is the init process that first runs inside a new namespace to setup mounts, users, networking,
19
+// and other options required for the new container.
20
+func Init(container *libcontainer.Container, console string, pipe io.ReadCloser, args []string) error {
19 21
 	rootfs, err := resolveRootfs()
20 22
 	if err != nil {
21 23
 		return err
22 24
deleted file mode 100644
... ...
@@ -1,89 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"encoding/json"
5
-	"errors"
6
-	"flag"
7
-	"github.com/dotcloud/docker/pkg/libcontainer"
8
-	"io/ioutil"
9
-	"log"
10
-	"os"
11
-	"strconv"
12
-)
13
-
14
-var (
15
-	ErrUnsupported    = errors.New("Unsupported method")
16
-	ErrWrongArguments = errors.New("Wrong argument count")
17
-)
18
-
19
-func main() {
20
-	var (
21
-		console = flag.String("console", "", "Console (pty slave) name")
22
-		tty     = flag.Bool("tty", false, "Create a tty")
23
-		pipeFd  = flag.Int("pipe", 0, "sync pipe fd")
24
-	)
25
-	flag.Parse()
26
-
27
-	container, err := loadContainer()
28
-	if err != nil {
29
-		log.Fatal(err)
30
-	}
31
-
32
-	if flag.NArg() < 1 {
33
-		log.Fatal(ErrWrongArguments)
34
-	}
35
-	switch flag.Arg(0) {
36
-	case "exec": // this is executed outside of the namespace in the cwd
37
-		var exitCode int
38
-		nspid, err := readPid()
39
-		if err != nil {
40
-			if !os.IsNotExist(err) {
41
-				log.Fatal(err)
42
-			}
43
-		}
44
-		if nspid > 0 {
45
-			exitCode, err = execinCommand(container, nspid, flag.Args()[1:])
46
-		} else {
47
-			exitCode, err = execCommand(container, *tty, flag.Args()[1:])
48
-		}
49
-		if err != nil {
50
-			log.Fatal(err)
51
-		}
52
-		os.Exit(exitCode)
53
-	case "init": // this is executed inside of the namespace to setup the container
54
-		if flag.NArg() < 2 {
55
-			log.Fatal(ErrWrongArguments)
56
-		}
57
-		if err := initCommand(container, *console, os.NewFile(uintptr(*pipeFd), "pipe"), flag.Args()[1:]); err != nil {
58
-			log.Fatal(err)
59
-		}
60
-	default:
61
-		log.Fatalf("command not supported for nsinit %s", flag.Arg(0))
62
-	}
63
-}
64
-
65
-func loadContainer() (*libcontainer.Container, error) {
66
-	f, err := os.Open("container.json")
67
-	if err != nil {
68
-		return nil, err
69
-	}
70
-	defer f.Close()
71
-
72
-	var container *libcontainer.Container
73
-	if err := json.NewDecoder(f).Decode(&container); err != nil {
74
-		return nil, err
75
-	}
76
-	return container, nil
77
-}
78
-
79
-func readPid() (int, error) {
80
-	data, err := ioutil.ReadFile(".nspid")
81
-	if err != nil {
82
-		return -1, err
83
-	}
84
-	pid, err := strconv.Atoi(string(data))
85
-	if err != nil {
86
-		return -1, err
87
-	}
88
-	return pid, nil
89
-}
... ...
@@ -1,6 +1,6 @@
1 1
 // +build linux
2 2
 
3
-package main
3
+package nsinit
4 4
 
5 5
 import (
6 6
 	"fmt"
... ...
@@ -1,4 +1,4 @@
1
-package main
1
+package nsinit
2 2
 
3 3
 import (
4 4
 	"github.com/dotcloud/docker/pkg/libcontainer"
5 5
new file mode 100644
... ...
@@ -0,0 +1,90 @@
0
+package main
1
+
2
+import (
3
+	"encoding/json"
4
+	"errors"
5
+	"flag"
6
+	"github.com/dotcloud/docker/pkg/libcontainer"
7
+	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
8
+	"io/ioutil"
9
+	"log"
10
+	"os"
11
+	"strconv"
12
+)
13
+
14
+var (
15
+	ErrUnsupported    = errors.New("Unsupported method")
16
+	ErrWrongArguments = errors.New("Wrong argument count")
17
+)
18
+
19
+func main() {
20
+	var (
21
+		console = flag.String("console", "", "Console (pty slave) name")
22
+		tty     = flag.Bool("tty", false, "Create a tty")
23
+		pipeFd  = flag.Int("pipe", 0, "sync pipe fd")
24
+	)
25
+	flag.Parse()
26
+
27
+	container, err := loadContainer()
28
+	if err != nil {
29
+		log.Fatal(err)
30
+	}
31
+
32
+	if flag.NArg() < 1 {
33
+		log.Fatal(ErrWrongArguments)
34
+	}
35
+	switch flag.Arg(0) {
36
+	case "exec": // this is executed outside of the namespace in the cwd
37
+		var exitCode int
38
+		nspid, err := readPid()
39
+		if err != nil {
40
+			if !os.IsNotExist(err) {
41
+				log.Fatal(err)
42
+			}
43
+		}
44
+		if nspid > 0 {
45
+			exitCode, err = nsinit.ExecIn(container, nspid, flag.Args()[1:])
46
+		} else {
47
+			exitCode, err = nsinit.Exec(container, *tty, flag.Args()[1:])
48
+		}
49
+		if err != nil {
50
+			log.Fatal(err)
51
+		}
52
+		os.Exit(exitCode)
53
+	case "init": // this is executed inside of the namespace to setup the container
54
+		if flag.NArg() < 2 {
55
+			log.Fatal(ErrWrongArguments)
56
+		}
57
+		if err := nsinit.Init(container, *console, os.NewFile(uintptr(*pipeFd), "pipe"), flag.Args()[1:]); err != nil {
58
+			log.Fatal(err)
59
+		}
60
+	default:
61
+		log.Fatalf("command not supported for nsinit %s", flag.Arg(0))
62
+	}
63
+}
64
+
65
+func loadContainer() (*libcontainer.Container, error) {
66
+	f, err := os.Open("container.json")
67
+	if err != nil {
68
+		return nil, err
69
+	}
70
+	defer f.Close()
71
+
72
+	var container *libcontainer.Container
73
+	if err := json.NewDecoder(f).Decode(&container); err != nil {
74
+		return nil, err
75
+	}
76
+	return container, nil
77
+}
78
+
79
+func readPid() (int, error) {
80
+	data, err := ioutil.ReadFile(".nspid")
81
+	if err != nil {
82
+		return -1, err
83
+	}
84
+	pid, err := strconv.Atoi(string(data))
85
+	if err != nil {
86
+		return -1, err
87
+	}
88
+	return pid, nil
89
+}