init.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // +build linux
  2. package lxc
  3. import (
  4. "encoding/json"
  5. "flag"
  6. "fmt"
  7. "os"
  8. "os/exec"
  9. "runtime"
  10. "strings"
  11. "syscall"
  12. "github.com/Sirupsen/logrus"
  13. "github.com/docker/docker/pkg/reexec"
  14. )
  15. // InitArgs contains 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. logrus.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. logrus.Infof("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. dockerenv, err := os.Open(".dockerenv")
  94. if err != nil {
  95. return fmt.Errorf("Unable to load environment variables: %v", err)
  96. }
  97. defer dockerenv.Close()
  98. if err := json.NewDecoder(dockerenv).Decode(&env); err != nil {
  99. return fmt.Errorf("Unable to decode environment variables: %v", err)
  100. }
  101. // Propagate the plugin-specific container env variable
  102. env = append(env, "container="+os.Getenv("container"))
  103. args.Env = env
  104. os.Clearenv()
  105. for _, kv := range args.Env {
  106. parts := strings.SplitN(kv, "=", 2)
  107. if len(parts) == 1 {
  108. parts = append(parts, "")
  109. }
  110. os.Setenv(parts[0], parts[1])
  111. }
  112. return nil
  113. }
  114. // Setup working directory
  115. func setupWorkingDirectory(args *InitArgs) error {
  116. if args.WorkDir == "" {
  117. return nil
  118. }
  119. if err := syscall.Chdir(args.WorkDir); err != nil {
  120. return fmt.Errorf("Unable to change dir to %v: %v", args.WorkDir, err)
  121. }
  122. return nil
  123. }