cloudinitexecute.go 4.9 KB

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