|
@@ -2,19 +2,116 @@ package lxc
|
|
|
|
|
|
import (
|
|
import (
|
|
"encoding/json"
|
|
"encoding/json"
|
|
|
|
+ "flag"
|
|
"fmt"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
|
|
+ "log"
|
|
"net"
|
|
"net"
|
|
"os"
|
|
"os"
|
|
|
|
+ "os/exec"
|
|
|
|
+ "runtime"
|
|
"strings"
|
|
"strings"
|
|
"syscall"
|
|
"syscall"
|
|
|
|
|
|
- "github.com/docker/docker/daemon/execdriver"
|
|
|
|
|
|
+ "github.com/docker/docker/reexec"
|
|
"github.com/docker/libcontainer/netlink"
|
|
"github.com/docker/libcontainer/netlink"
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+// Args provided to the init function for a driver
|
|
|
|
+type InitArgs struct {
|
|
|
|
+ User string
|
|
|
|
+ Gateway string
|
|
|
|
+ Ip string
|
|
|
|
+ WorkDir string
|
|
|
|
+ Privileged bool
|
|
|
|
+ Env []string
|
|
|
|
+ Args []string
|
|
|
|
+ Mtu int
|
|
|
|
+ Console string
|
|
|
|
+ Pipe int
|
|
|
|
+ Root string
|
|
|
|
+ CapAdd string
|
|
|
|
+ CapDrop string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func init() {
|
|
|
|
+ // like always lxc requires a hack to get this to work
|
|
|
|
+ reexec.Register("/.dockerinit", dockerInititalizer)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func dockerInititalizer() {
|
|
|
|
+ initializer()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// initializer is the lxc driver's init function that is run inside the namespace to setup
|
|
|
|
+// additional configurations
|
|
|
|
+func initializer() {
|
|
|
|
+ runtime.LockOSThread()
|
|
|
|
+
|
|
|
|
+ args := getArgs()
|
|
|
|
+
|
|
|
|
+ if err := setupNamespace(args); err != nil {
|
|
|
|
+ log.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func setupNamespace(args *InitArgs) error {
|
|
|
|
+ if err := setupEnv(args); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if err := setupHostname(args); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if err := setupNetworking(args); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if err := finalizeNamespace(args); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ path, err := exec.LookPath(args.Args[0])
|
|
|
|
+ if err != nil {
|
|
|
|
+ log.Printf("Unable to locate %v", args.Args[0])
|
|
|
|
+ os.Exit(127)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if err := syscall.Exec(path, args.Args, os.Environ()); err != nil {
|
|
|
|
+ return fmt.Errorf("dockerinit unable to execute %s - %s", path, err)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func getArgs() *InitArgs {
|
|
|
|
+ var (
|
|
|
|
+ // Get cmdline arguments
|
|
|
|
+ user = flag.String("u", "", "username or uid")
|
|
|
|
+ gateway = flag.String("g", "", "gateway address")
|
|
|
|
+ ip = flag.String("i", "", "ip address")
|
|
|
|
+ workDir = flag.String("w", "", "workdir")
|
|
|
|
+ privileged = flag.Bool("privileged", false, "privileged mode")
|
|
|
|
+ mtu = flag.Int("mtu", 1500, "interface mtu")
|
|
|
|
+ capAdd = flag.String("cap-add", "", "capabilities to add")
|
|
|
|
+ capDrop = flag.String("cap-drop", "", "capabilities to drop")
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ flag.Parse()
|
|
|
|
+
|
|
|
|
+ return &InitArgs{
|
|
|
|
+ User: *user,
|
|
|
|
+ Gateway: *gateway,
|
|
|
|
+ Ip: *ip,
|
|
|
|
+ WorkDir: *workDir,
|
|
|
|
+ Privileged: *privileged,
|
|
|
|
+ Args: flag.Args(),
|
|
|
|
+ Mtu: *mtu,
|
|
|
|
+ CapAdd: *capAdd,
|
|
|
|
+ CapDrop: *capDrop,
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
// Clear environment pollution introduced by lxc-start
|
|
// Clear environment pollution introduced by lxc-start
|
|
-func setupEnv(args *execdriver.InitArgs) error {
|
|
|
|
|
|
+func setupEnv(args *InitArgs) error {
|
|
// Get env
|
|
// Get env
|
|
var env []string
|
|
var env []string
|
|
content, err := ioutil.ReadFile(".dockerenv")
|
|
content, err := ioutil.ReadFile(".dockerenv")
|
|
@@ -41,7 +138,7 @@ func setupEnv(args *execdriver.InitArgs) error {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func setupHostname(args *execdriver.InitArgs) error {
|
|
|
|
|
|
+func setupHostname(args *InitArgs) error {
|
|
hostname := getEnv(args, "HOSTNAME")
|
|
hostname := getEnv(args, "HOSTNAME")
|
|
if hostname == "" {
|
|
if hostname == "" {
|
|
return nil
|
|
return nil
|
|
@@ -50,7 +147,7 @@ func setupHostname(args *execdriver.InitArgs) error {
|
|
}
|
|
}
|
|
|
|
|
|
// Setup networking
|
|
// Setup networking
|
|
-func setupNetworking(args *execdriver.InitArgs) error {
|
|
|
|
|
|
+func setupNetworking(args *InitArgs) error {
|
|
if args.Ip != "" {
|
|
if args.Ip != "" {
|
|
// eth0
|
|
// eth0
|
|
iface, err := net.InterfaceByName("eth0")
|
|
iface, err := net.InterfaceByName("eth0")
|
|
@@ -95,7 +192,7 @@ func setupNetworking(args *execdriver.InitArgs) error {
|
|
}
|
|
}
|
|
|
|
|
|
// Setup working directory
|
|
// Setup working directory
|
|
-func setupWorkingDirectory(args *execdriver.InitArgs) error {
|
|
|
|
|
|
+func setupWorkingDirectory(args *InitArgs) error {
|
|
if args.WorkDir == "" {
|
|
if args.WorkDir == "" {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
@@ -105,7 +202,7 @@ func setupWorkingDirectory(args *execdriver.InitArgs) error {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func getEnv(args *execdriver.InitArgs, key string) string {
|
|
|
|
|
|
+func getEnv(args *InitArgs, key string) string {
|
|
for _, kv := range args.Env {
|
|
for _, kv := range args.Env {
|
|
parts := strings.SplitN(kv, "=", 2)
|
|
parts := strings.SplitN(kv, "=", 2)
|
|
if parts[0] == key && len(parts) == 2 {
|
|
if parts[0] == key && len(parts) == 2 {
|