Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit 6415e8b

Browse files
committed
Initial commit of libcontainer
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
0 parents  commit 6415e8b

20 files changed

+1531
-0
lines changed

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
2+
Guillaume Charmes <guillaume@dotcloud.com> (@creack)

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
## libcontainer - reference implementation for containers
2+
3+
#### playground
4+
5+
6+
Use the cli package to test out functionality
7+
8+
First setup a container configuration. You will need a root fs, better go the path to a
9+
stopped docker container and use that.
10+
11+
12+
```json
13+
{
14+
"id": "koye",
15+
"namespace_pid": 12265,
16+
"command": {
17+
"args": [
18+
"/bin/bash"
19+
],
20+
"environment": [
21+
"HOME=/",
22+
"PATH=PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin",
23+
"container=docker",
24+
"TERM=xterm"
25+
]
26+
},
27+
"rootfs": "/root/development/gocode/src/github.com/docker/libcontainer/namespaces/ubuntu",
28+
"network": null,
29+
"user": "",
30+
"working_dir": "",
31+
"namespaces": [
32+
"NEWNET",
33+
"NEWIPC",
34+
"NEWNS",
35+
"NEWPID",
36+
"NEWUTS"
37+
],
38+
"capabilities": [
39+
"SETPCAP",
40+
"SYS_MODULE",
41+
"SYS_RAWIO",
42+
"SYS_PACCT",
43+
"SYS_ADMIN",
44+
"SYS_NICE",
45+
"SYS_RESOURCE",
46+
"SYS_TIME",
47+
"SYS_TTY_CONFIG",
48+
"MKNOD",
49+
"AUDIT_WRITE",
50+
"AUDIT_CONTROL",
51+
"MAC_OVERRIDE",
52+
"MAC_ADMIN"
53+
]
54+
}
55+
```
56+
57+
After you have a json file and a rootfs path to use just run:
58+
`./cli exec container.json`
59+
60+
61+
If you want to attach to an existing namespace just use the same json
62+
file with the container still running and do:
63+
`./cli execin container.json`

capabilities/capabilities.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package capabilities
2+
3+
import (
4+
"github.com/dotcloud/docker/pkg/libcontainer"
5+
"github.com/syndtr/gocapability/capability"
6+
"os"
7+
)
8+
9+
var capMap = map[libcontainer.Capability]capability.Cap{
10+
libcontainer.CAP_SETPCAP: capability.CAP_SETPCAP,
11+
libcontainer.CAP_SYS_MODULE: capability.CAP_SYS_MODULE,
12+
libcontainer.CAP_SYS_RAWIO: capability.CAP_SYS_RAWIO,
13+
libcontainer.CAP_SYS_PACCT: capability.CAP_SYS_PACCT,
14+
libcontainer.CAP_SYS_ADMIN: capability.CAP_SYS_ADMIN,
15+
libcontainer.CAP_SYS_NICE: capability.CAP_SYS_NICE,
16+
libcontainer.CAP_SYS_RESOURCE: capability.CAP_SYS_RESOURCE,
17+
libcontainer.CAP_SYS_TIME: capability.CAP_SYS_TIME,
18+
libcontainer.CAP_SYS_TTY_CONFIG: capability.CAP_SYS_TTY_CONFIG,
19+
libcontainer.CAP_MKNOD: capability.CAP_MKNOD,
20+
libcontainer.CAP_AUDIT_WRITE: capability.CAP_AUDIT_WRITE,
21+
libcontainer.CAP_AUDIT_CONTROL: capability.CAP_AUDIT_CONTROL,
22+
libcontainer.CAP_MAC_OVERRIDE: capability.CAP_MAC_OVERRIDE,
23+
libcontainer.CAP_MAC_ADMIN: capability.CAP_MAC_ADMIN,
24+
}
25+
26+
// DropCapabilities drops capabilities for the current process based
27+
// on the container's configuration.
28+
func DropCapabilities(container *libcontainer.Container) error {
29+
if drop := getCapabilities(container); len(drop) > 0 {
30+
c, err := capability.NewPid(os.Getpid())
31+
if err != nil {
32+
return err
33+
}
34+
c.Unset(capability.CAPS|capability.BOUNDS, drop...)
35+
36+
if err := c.Apply(capability.CAPS | capability.BOUNDS); err != nil {
37+
return err
38+
}
39+
}
40+
return nil
41+
}
42+
43+
func getCapabilities(container *libcontainer.Container) []capability.Cap {
44+
drop := []capability.Cap{}
45+
for _, c := range container.Capabilities {
46+
drop = append(drop, capMap[c])
47+
}
48+
return drop
49+
}

cli/main.go

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"flag"
6+
"fmt"
7+
"github.com/dotcloud/docker/pkg/libcontainer"
8+
"github.com/dotcloud/docker/pkg/libcontainer/namespaces"
9+
"github.com/dotcloud/docker/pkg/libcontainer/network"
10+
"github.com/dotcloud/docker/pkg/libcontainer/utils"
11+
"os"
12+
)
13+
14+
var (
15+
displayPid bool
16+
newCommand string
17+
usrNet bool
18+
)
19+
20+
func init() {
21+
flag.BoolVar(&displayPid, "pid", false, "display the pid before waiting")
22+
flag.StringVar(&newCommand, "cmd", "/bin/bash", "command to run in the existing namespace")
23+
flag.BoolVar(&usrNet, "net", false, "user a net namespace")
24+
flag.Parse()
25+
}
26+
27+
func exec(container *libcontainer.Container) error {
28+
var (
29+
netFile *os.File
30+
err error
31+
)
32+
container.NetNsFd = 0
33+
34+
if usrNet {
35+
netFile, err = os.Open("/root/nsroot/test")
36+
if err != nil {
37+
return err
38+
}
39+
container.NetNsFd = netFile.Fd()
40+
}
41+
42+
pid, err := namespaces.Exec(container)
43+
if err != nil {
44+
return fmt.Errorf("error exec container %s", err)
45+
}
46+
47+
if displayPid {
48+
fmt.Println(pid)
49+
}
50+
51+
exitcode, err := utils.WaitOnPid(pid)
52+
if err != nil {
53+
return fmt.Errorf("error waiting on child %s", err)
54+
}
55+
fmt.Println(exitcode)
56+
if usrNet {
57+
netFile.Close()
58+
if err := network.DeleteNetworkNamespace("/root/nsroot/test"); err != nil {
59+
return err
60+
}
61+
}
62+
os.Exit(exitcode)
63+
return nil
64+
}
65+
66+
func execIn(container *libcontainer.Container) error {
67+
f, err := os.Open("/root/nsroot/test")
68+
if err != nil {
69+
return err
70+
}
71+
container.NetNsFd = f.Fd()
72+
pid, err := namespaces.ExecIn(container, &libcontainer.Command{
73+
Env: container.Command.Env,
74+
Args: []string{
75+
newCommand,
76+
},
77+
})
78+
if err != nil {
79+
return fmt.Errorf("error exexin container %s", err)
80+
}
81+
exitcode, err := utils.WaitOnPid(pid)
82+
if err != nil {
83+
return fmt.Errorf("error waiting on child %s", err)
84+
}
85+
os.Exit(exitcode)
86+
return nil
87+
}
88+
89+
func createNet(config *libcontainer.Network) error {
90+
root := "/root/nsroot"
91+
if err := network.SetupNamespaceMountDir(root); err != nil {
92+
return err
93+
}
94+
95+
nspath := root + "/test"
96+
if err := network.CreateNetworkNamespace(nspath); err != nil {
97+
return nil
98+
}
99+
if err := network.CreateVethPair("veth0", config.TempVethName); err != nil {
100+
return err
101+
}
102+
if err := network.SetInterfaceMaster("veth0", config.Bridge); err != nil {
103+
return err
104+
}
105+
if err := network.InterfaceUp("veth0"); err != nil {
106+
return err
107+
}
108+
109+
f, err := os.Open(nspath)
110+
if err != nil {
111+
return err
112+
}
113+
defer f.Close()
114+
115+
if err := network.SetInterfaceInNamespaceFd("veth1", int(f.Fd())); err != nil {
116+
return err
117+
}
118+
119+
/*
120+
if err := network.SetupVethInsideNamespace(f.Fd(), config); err != nil {
121+
return err
122+
}
123+
*/
124+
return nil
125+
}
126+
127+
func printErr(err error) {
128+
fmt.Fprintln(os.Stderr, err)
129+
os.Exit(1)
130+
}
131+
132+
func main() {
133+
var (
134+
err error
135+
cliCmd = flag.Arg(0)
136+
config = flag.Arg(1)
137+
)
138+
f, err := os.Open(config)
139+
if err != nil {
140+
printErr(err)
141+
}
142+
143+
dec := json.NewDecoder(f)
144+
var container *libcontainer.Container
145+
146+
if err := dec.Decode(&container); err != nil {
147+
printErr(err)
148+
}
149+
f.Close()
150+
151+
switch cliCmd {
152+
case "exec":
153+
err = exec(container)
154+
case "execin":
155+
err = execIn(container)
156+
case "net":
157+
err = createNet(&libcontainer.Network{
158+
TempVethName: "veth1",
159+
IP: "172.17.0.100/16",
160+
Gateway: "172.17.42.1",
161+
Mtu: 1500,
162+
Bridge: "docker0",
163+
})
164+
default:
165+
err = fmt.Errorf("command not supported: %s", cliCmd)
166+
}
167+
168+
if err != nil {
169+
printErr(err)
170+
}
171+
}

container.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package libcontainer
2+
3+
type Container struct {
4+
ID string `json:"id,omitempty"`
5+
NsPid int `json:"namespace_pid,omitempty"`
6+
Command *Command `json:"command,omitempty"`
7+
RootFs string `json:"rootfs,omitempty"`
8+
ReadonlyFs bool `json:"readonly_fs,omitempty"`
9+
NetNsFd uintptr `json:"network_namespace_fd,omitempty"`
10+
User string `json:"user,omitempty"`
11+
WorkingDir string `json:"working_dir,omitempty"`
12+
Namespaces Namespaces `json:"namespaces,omitempty"`
13+
Capabilities Capabilities `json:"capabilities,omitempty"`
14+
}
15+
16+
type Command struct {
17+
Args []string `json:"args,omitempty"`
18+
Env []string `json:"environment,omitempty"`
19+
}
20+
21+
type Network struct {
22+
TempVethName string `json:"temp_veth,omitempty"`
23+
IP string `json:"ip,omitempty"`
24+
Gateway string `json:"gateway,omitempty"`
25+
Bridge string `json:"bridge,omitempty"`
26+
Mtu int `json:"mtu,omitempty"`
27+
}

container.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"id": "koye",
3+
"namespace_pid": 3117,
4+
"command": {
5+
"args": [
6+
"/bin/bash"
7+
],
8+
"environment": [
9+
"HOME=/",
10+
"PATH=PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin",
11+
"container=docker",
12+
"TERM=xterm"
13+
]
14+
},
15+
"rootfs": "/root/main/mycontainer",
16+
"namespaces": [
17+
"NEWIPC",
18+
"NEWNS",
19+
"NEWPID",
20+
"NEWUTS"
21+
],
22+
"capabilities": [
23+
"SETPCAP",
24+
"SYS_MODULE",
25+
"SYS_RAWIO",
26+
"SYS_PACCT",
27+
"SYS_ADMIN",
28+
"SYS_NICE",
29+
"SYS_RESOURCE",
30+
"SYS_TIME",
31+
"SYS_TTY_CONFIG",
32+
"MKNOD",
33+
"AUDIT_WRITE",
34+
"AUDIT_CONTROL",
35+
"MAC_OVERRIDE",
36+
"MAC_ADMIN"
37+
]
38+
}

errors.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package libcontainer
2+
3+
import (
4+
"errors"
5+
)
6+
7+
var (
8+
ErrInvalidPid = errors.New("no ns pid found")
9+
)

0 commit comments

Comments
 (0)