init.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. workDir = flag.String("w", "", "workdir")
  69. privileged = flag.Bool("privileged", false, "privileged mode")
  70. capAdd = flag.String("cap-add", "", "capabilities to add")
  71. capDrop = flag.String("cap-drop", "", "capabilities to drop")
  72. )
  73. flag.Parse()
  74. return &InitArgs{
  75. User: *user,
  76. WorkDir: *workDir,
  77. Privileged: *privileged,
  78. Args: flag.Args(),
  79. CapAdd: *capAdd,
  80. CapDrop: *capDrop,
  81. }
  82. }
  83. // Clear environment pollution introduced by lxc-start
  84. func setupEnv(args *InitArgs) error {
  85. // Get env
  86. var env []string
  87. content, err := ioutil.ReadFile(".dockerenv")
  88. if err != nil {
  89. return fmt.Errorf("Unable to load environment variables: %v", err)
  90. }
  91. if err := json.Unmarshal(content, &env); err != nil {
  92. return fmt.Errorf("Unable to unmarshal environment variables: %v", err)
  93. }
  94. // Propagate the plugin-specific container env variable
  95. env = append(env, "container="+os.Getenv("container"))
  96. args.Env = env
  97. os.Clearenv()
  98. for _, kv := range args.Env {
  99. parts := strings.SplitN(kv, "=", 2)
  100. if len(parts) == 1 {
  101. parts = append(parts, "")
  102. }
  103. os.Setenv(parts[0], parts[1])
  104. }
  105. return nil
  106. }
  107. // Setup working directory
  108. func setupWorkingDirectory(args *InitArgs) error {
  109. if args.WorkDir == "" {
  110. return nil
  111. }
  112. if err := syscall.Chdir(args.WorkDir); err != nil {
  113. return fmt.Errorf("Unable to change dir to %v: %v", args.WorkDir, err)
  114. }
  115. return nil
  116. }
  117. func getEnv(args *InitArgs, key string) string {
  118. for _, kv := range args.Env {
  119. parts := strings.SplitN(kv, "=", 2)
  120. if parts[0] == key && len(parts) == 2 {
  121. return parts[1]
  122. }
  123. }
  124. return ""
  125. }