github.com/dougm/docker@v1.5.0/daemon/execdriver/lxc/init.go (about)

     1  package lxc
     2  
     3  import (
     4  	"encoding/json"
     5  	"flag"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"log"
     9  	"os"
    10  	"os/exec"
    11  	"runtime"
    12  	"strings"
    13  	"syscall"
    14  
    15  	"github.com/docker/docker/pkg/reexec"
    16  )
    17  
    18  // Args provided to the init function for a driver
    19  type InitArgs struct {
    20  	User       string
    21  	Gateway    string
    22  	Ip         string
    23  	WorkDir    string
    24  	Privileged bool
    25  	Env        []string
    26  	Args       []string
    27  	Mtu        int
    28  	Console    string
    29  	Pipe       int
    30  	Root       string
    31  	CapAdd     string
    32  	CapDrop    string
    33  }
    34  
    35  func init() {
    36  	// like always lxc requires a hack to get this to work
    37  	reexec.Register("/.dockerinit", dockerInititalizer)
    38  }
    39  
    40  func dockerInititalizer() {
    41  	initializer()
    42  }
    43  
    44  // initializer is the lxc driver's init function that is run inside the namespace to setup
    45  // additional configurations
    46  func initializer() {
    47  	runtime.LockOSThread()
    48  
    49  	args := getArgs()
    50  
    51  	if err := setupNamespace(args); err != nil {
    52  		log.Fatal(err)
    53  	}
    54  }
    55  
    56  func setupNamespace(args *InitArgs) error {
    57  	if err := setupEnv(args); err != nil {
    58  		return err
    59  	}
    60  
    61  	if err := finalizeNamespace(args); err != nil {
    62  		return err
    63  	}
    64  
    65  	path, err := exec.LookPath(args.Args[0])
    66  	if err != nil {
    67  		log.Printf("Unable to locate %v", args.Args[0])
    68  		os.Exit(127)
    69  	}
    70  
    71  	if err := syscall.Exec(path, args.Args, os.Environ()); err != nil {
    72  		return fmt.Errorf("dockerinit unable to execute %s - %s", path, err)
    73  	}
    74  
    75  	return nil
    76  }
    77  
    78  func getArgs() *InitArgs {
    79  	var (
    80  		// Get cmdline arguments
    81  		user       = flag.String("u", "", "username or uid")
    82  		gateway    = flag.String("g", "", "gateway address")
    83  		ip         = flag.String("i", "", "ip address")
    84  		workDir    = flag.String("w", "", "workdir")
    85  		privileged = flag.Bool("privileged", false, "privileged mode")
    86  		mtu        = flag.Int("mtu", 1500, "interface mtu")
    87  		capAdd     = flag.String("cap-add", "", "capabilities to add")
    88  		capDrop    = flag.String("cap-drop", "", "capabilities to drop")
    89  	)
    90  
    91  	flag.Parse()
    92  
    93  	return &InitArgs{
    94  		User:       *user,
    95  		Gateway:    *gateway,
    96  		Ip:         *ip,
    97  		WorkDir:    *workDir,
    98  		Privileged: *privileged,
    99  		Args:       flag.Args(),
   100  		Mtu:        *mtu,
   101  		CapAdd:     *capAdd,
   102  		CapDrop:    *capDrop,
   103  	}
   104  }
   105  
   106  // Clear environment pollution introduced by lxc-start
   107  func setupEnv(args *InitArgs) error {
   108  	// Get env
   109  	var env []string
   110  	content, err := ioutil.ReadFile(".dockerenv")
   111  	if err != nil {
   112  		return fmt.Errorf("Unable to load environment variables: %v", err)
   113  	}
   114  	if err := json.Unmarshal(content, &env); err != nil {
   115  		return fmt.Errorf("Unable to unmarshal environment variables: %v", err)
   116  	}
   117  	// Propagate the plugin-specific container env variable
   118  	env = append(env, "container="+os.Getenv("container"))
   119  
   120  	args.Env = env
   121  
   122  	os.Clearenv()
   123  	for _, kv := range args.Env {
   124  		parts := strings.SplitN(kv, "=", 2)
   125  		if len(parts) == 1 {
   126  			parts = append(parts, "")
   127  		}
   128  		os.Setenv(parts[0], parts[1])
   129  	}
   130  
   131  	return nil
   132  }
   133  
   134  // Setup working directory
   135  func setupWorkingDirectory(args *InitArgs) error {
   136  	if args.WorkDir == "" {
   137  		return nil
   138  	}
   139  	if err := syscall.Chdir(args.WorkDir); err != nil {
   140  		return fmt.Errorf("Unable to change dir to %v: %v", args.WorkDir, err)
   141  	}
   142  	return nil
   143  }
   144  
   145  func getEnv(args *InitArgs, key string) string {
   146  	for _, kv := range args.Env {
   147  		parts := strings.SplitN(kv, "=", 2)
   148  		if parts[0] == key && len(parts) == 2 {
   149  			return parts[1]
   150  		}
   151  	}
   152  	return ""
   153  }