cloudinitexecute.go 4.6 KB

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