cloudinitexecute.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package cloudinitexecute
  2. import (
  3. "flag"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "os/exec"
  8. "path"
  9. "strings"
  10. log "github.com/Sirupsen/logrus"
  11. "github.com/coreos/coreos-cloudinit/system"
  12. rancherConfig "github.com/rancher/os/config"
  13. "github.com/rancher/os/docker"
  14. "github.com/rancher/os/util"
  15. "golang.org/x/net/context"
  16. )
  17. const (
  18. resizeStamp = "/var/lib/rancher/resizefs.done"
  19. sshKeyName = "rancheros-cloud-config"
  20. )
  21. var (
  22. console bool
  23. preConsole bool
  24. flags *flag.FlagSet
  25. )
  26. func init() {
  27. flags = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
  28. flags.BoolVar(&console, "console", false, "apply console configuration")
  29. flags.BoolVar(&preConsole, "pre-console", false, "apply pre-console configuration")
  30. }
  31. func Main() {
  32. flags.Parse(os.Args[1:])
  33. log.Infof("Running cloud-init-execute: pre-console=%v, console=%v", preConsole, console)
  34. cfg := rancherConfig.LoadConfig()
  35. if !console && !preConsole {
  36. console = true
  37. preConsole = true
  38. }
  39. if console {
  40. ApplyConsole(cfg)
  41. }
  42. if preConsole {
  43. applyPreConsole(cfg)
  44. }
  45. }
  46. func ApplyConsole(cfg *rancherConfig.CloudConfig) {
  47. if len(cfg.SSHAuthorizedKeys) > 0 {
  48. authorizeSSHKeys("rancher", cfg.SSHAuthorizedKeys, sshKeyName)
  49. authorizeSSHKeys("docker", cfg.SSHAuthorizedKeys, sshKeyName)
  50. }
  51. WriteFiles(cfg, "console")
  52. for _, mount := range cfg.Mounts {
  53. if len(mount) != 4 {
  54. log.Errorf("Unable to mount %s: must specify exactly four arguments", mount[1])
  55. }
  56. device := util.ResolveDevice(mount[0])
  57. if mount[2] == "swap" {
  58. cmd := exec.Command("swapon", device)
  59. cmd.Stdout = os.Stdout
  60. cmd.Stderr = os.Stderr
  61. err := cmd.Run()
  62. if err != nil {
  63. log.Errorf("Unable to swapon %s: %v", device, err)
  64. }
  65. continue
  66. }
  67. cmdArgs := []string{device, mount[1]}
  68. if mount[2] != "" {
  69. cmdArgs = append(cmdArgs, "-t", mount[2])
  70. }
  71. if mount[3] != "" {
  72. cmdArgs = append(cmdArgs, "-o", mount[3])
  73. }
  74. cmd := exec.Command("mount", cmdArgs...)
  75. cmd.Stdout = os.Stdout
  76. cmd.Stderr = os.Stderr
  77. if err := cmd.Run(); err != nil {
  78. log.Errorf("Failed to mount %s: %v", mount[1], err)
  79. }
  80. }
  81. for _, runcmd := range cfg.Runcmd {
  82. if len(runcmd) == 0 {
  83. continue
  84. }
  85. cmd := exec.Command(runcmd[0], runcmd[1:]...)
  86. cmd.Stdout = os.Stdout
  87. cmd.Stderr = os.Stderr
  88. if err := cmd.Run(); err != nil {
  89. log.Errorf("Failed to run %s: %v", runcmd, err)
  90. }
  91. }
  92. }
  93. func WriteFiles(cfg *rancherConfig.CloudConfig, container string) {
  94. for _, file := range cfg.WriteFiles {
  95. fileContainer := file.Container
  96. if fileContainer == "" {
  97. fileContainer = "console"
  98. }
  99. if fileContainer != container {
  100. continue
  101. }
  102. f := system.File{
  103. File: file.File,
  104. }
  105. fullPath, err := system.WriteFile(&f, "/")
  106. if err != nil {
  107. log.WithFields(log.Fields{"err": err, "path": fullPath}).Error("Error writing file")
  108. continue
  109. }
  110. log.Printf("Wrote file %s to filesystem", fullPath)
  111. }
  112. }
  113. func applyPreConsole(cfg *rancherConfig.CloudConfig) {
  114. if _, err := os.Stat(resizeStamp); os.IsNotExist(err) && cfg.Rancher.ResizeDevice != "" {
  115. if err := resizeDevice(cfg); err == nil {
  116. os.Create(resizeStamp)
  117. } else {
  118. log.Errorf("Failed to resize %s: %s", cfg.Rancher.ResizeDevice, err)
  119. }
  120. }
  121. for k, v := range cfg.Rancher.Sysctl {
  122. elems := []string{"/proc", "sys"}
  123. elems = append(elems, strings.Split(k, ".")...)
  124. path := path.Join(elems...)
  125. if err := ioutil.WriteFile(path, []byte(v), 0644); err != nil {
  126. log.Errorf("Failed to set sysctl key %s: %s", k, err)
  127. }
  128. }
  129. client, err := docker.NewSystemClient()
  130. if err != nil {
  131. log.Error(err)
  132. }
  133. for _, restart := range cfg.Rancher.RestartServices {
  134. if err = client.ContainerRestart(context.Background(), restart, 10); err != nil {
  135. log.Error(err)
  136. }
  137. }
  138. }
  139. func resizeDevice(cfg *rancherConfig.CloudConfig) error {
  140. cmd := exec.Command("growpart", cfg.Rancher.ResizeDevice, "1")
  141. cmd.Stdout = os.Stdout
  142. cmd.Stderr = os.Stderr
  143. cmd.Run()
  144. cmd = exec.Command("partprobe", cfg.Rancher.ResizeDevice)
  145. cmd.Stdout = os.Stdout
  146. cmd.Stderr = os.Stderr
  147. err := cmd.Run()
  148. if err != nil {
  149. return err
  150. }
  151. cmd = exec.Command("resize2fs", fmt.Sprintf("%s1", cfg.Rancher.ResizeDevice))
  152. cmd.Stdout = os.Stdout
  153. cmd.Stderr = os.Stderr
  154. err = cmd.Run()
  155. if err != nil {
  156. return err
  157. }
  158. return nil
  159. }