init.go 3.2 KB

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