main.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package userdocker
  2. import (
  3. "io"
  4. "io/ioutil"
  5. "os"
  6. "path"
  7. "syscall"
  8. "time"
  9. "golang.org/x/net/context"
  10. "path/filepath"
  11. log "github.com/Sirupsen/logrus"
  12. composeClient "github.com/docker/libcompose/docker/client"
  13. "github.com/docker/libcompose/project"
  14. "github.com/rancher/os/cmd/control"
  15. "github.com/rancher/os/compose"
  16. "github.com/rancher/os/config"
  17. rosDocker "github.com/rancher/os/docker"
  18. "github.com/rancher/os/util"
  19. )
  20. const (
  21. DEFAULT_STORAGE_CONTEXT = "console"
  22. DOCKER_PID_FILE = "/var/run/docker.pid"
  23. DOCKER_COMMAND = "docker-init"
  24. userDocker = "user-docker"
  25. sourceDirectory = "/engine"
  26. destDirectory = "/var/lib/rancher/engine"
  27. )
  28. func Main() {
  29. if err := copyBinaries(sourceDirectory, destDirectory); err != nil {
  30. log.Fatal(err)
  31. }
  32. if err := syscall.Mount("/host/sys", "/sys", "", syscall.MS_BIND|syscall.MS_REC, ""); err != nil {
  33. log.Fatal(err)
  34. }
  35. cfg := config.LoadConfig()
  36. log.Fatal(startDocker(cfg))
  37. }
  38. func copyBinaries(source, dest string) error {
  39. if err := os.MkdirAll(dest, 0755); err != nil {
  40. return err
  41. }
  42. files, err := ioutil.ReadDir(dest)
  43. if err != nil {
  44. return err
  45. }
  46. for _, file := range files {
  47. if err = os.RemoveAll(path.Join(dest, file.Name())); err != nil {
  48. return err
  49. }
  50. }
  51. files, err = ioutil.ReadDir(source)
  52. if err != nil {
  53. return err
  54. }
  55. for _, file := range files {
  56. sourceFile := path.Join(source, file.Name())
  57. destFile := path.Join(dest, file.Name())
  58. in, err := os.Open(sourceFile)
  59. if err != nil {
  60. return err
  61. }
  62. out, err := os.Create(destFile)
  63. if err != nil {
  64. return err
  65. }
  66. if _, err = io.Copy(out, in); err != nil {
  67. return err
  68. }
  69. if err = out.Sync(); err != nil {
  70. return err
  71. }
  72. if err = in.Close(); err != nil {
  73. return err
  74. }
  75. if err = out.Close(); err != nil {
  76. return err
  77. }
  78. if err := os.Chmod(destFile, 0751); err != nil {
  79. return err
  80. }
  81. }
  82. return nil
  83. }
  84. func writeCerts(cfg *config.CloudConfig) error {
  85. outDir := control.ServerTlsPath
  86. if err := os.MkdirAll(outDir, 0700); err != nil {
  87. return err
  88. }
  89. caCertPath := filepath.Join(outDir, control.CaCert)
  90. caKeyPath := filepath.Join(outDir, control.CaKey)
  91. serverCertPath := filepath.Join(outDir, control.ServerCert)
  92. serverKeyPath := filepath.Join(outDir, control.ServerKey)
  93. if cfg.Rancher.Docker.CACert != "" {
  94. if err := util.WriteFileAtomic(caCertPath, []byte(cfg.Rancher.Docker.CACert), 0400); err != nil {
  95. return err
  96. }
  97. if err := util.WriteFileAtomic(caKeyPath, []byte(cfg.Rancher.Docker.CAKey), 0400); err != nil {
  98. return err
  99. }
  100. }
  101. if cfg.Rancher.Docker.ServerCert != "" {
  102. if err := util.WriteFileAtomic(serverCertPath, []byte(cfg.Rancher.Docker.ServerCert), 0400); err != nil {
  103. return err
  104. }
  105. if err := util.WriteFileAtomic(serverKeyPath, []byte(cfg.Rancher.Docker.ServerKey), 0400); err != nil {
  106. return err
  107. }
  108. }
  109. return nil
  110. }
  111. func startDocker(cfg *config.CloudConfig) error {
  112. storageContext := cfg.Rancher.Docker.StorageContext
  113. if storageContext == "" {
  114. storageContext = DEFAULT_STORAGE_CONTEXT
  115. }
  116. log.Infof("Starting Docker in context: %s", storageContext)
  117. p, err := compose.GetProject(cfg, true, false)
  118. if err != nil {
  119. return err
  120. }
  121. pid, err := waitForPid(storageContext, p)
  122. if err != nil {
  123. return err
  124. }
  125. log.Infof("%s PID %d", storageContext, pid)
  126. client, err := rosDocker.NewSystemClient()
  127. if err != nil {
  128. return err
  129. }
  130. dockerCfg := cfg.Rancher.Docker
  131. args := dockerCfg.FullArgs()
  132. log.Debugf("User Docker args: %v", args)
  133. if dockerCfg.TLS {
  134. if err := writeCerts(cfg); err != nil {
  135. return err
  136. }
  137. }
  138. info, err := client.ContainerInspect(context.Background(), storageContext)
  139. if err != nil {
  140. return err
  141. }
  142. cmd := []string{"docker-runc", "exec", "--", info.ID, "env"}
  143. log.Info(dockerCfg.AppendEnv())
  144. cmd = append(cmd, dockerCfg.AppendEnv()...)
  145. cmd = append(cmd, DOCKER_COMMAND)
  146. cmd = append(cmd, args...)
  147. log.Infof("Running %v", cmd)
  148. return syscall.Exec("/usr/bin/ros", cmd, os.Environ())
  149. }
  150. func waitForPid(service string, project *project.Project) (int, error) {
  151. log.Infof("Getting PID for service: %s", service)
  152. for {
  153. if pid, err := getPid(service, project); err != nil || pid == 0 {
  154. log.Infof("Waiting for %s : %d : %v", service, pid, err)
  155. time.Sleep(1 * time.Second)
  156. } else {
  157. return pid, err
  158. }
  159. }
  160. }
  161. func getPid(service string, project *project.Project) (int, error) {
  162. s, err := project.CreateService(service)
  163. if err != nil {
  164. return 0, err
  165. }
  166. containers, err := s.Containers(context.Background())
  167. if err != nil {
  168. return 0, err
  169. }
  170. if len(containers) == 0 {
  171. return 0, nil
  172. }
  173. client, err := composeClient.Create(composeClient.Options{
  174. Host: config.DOCKER_SYSTEM_HOST,
  175. })
  176. if err != nil {
  177. return 0, err
  178. }
  179. id, err := containers[0].ID()
  180. if err != nil {
  181. return 0, err
  182. }
  183. info, err := client.ContainerInspect(context.Background(), id)
  184. if err != nil || info.ID == "" {
  185. return 0, err
  186. }
  187. if info.State.Running {
  188. return info.State.Pid, nil
  189. }
  190. return 0, nil
  191. }