bootstrap.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package control
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "os/exec"
  7. "path/filepath"
  8. "strings"
  9. "time"
  10. "github.com/rancher/os/config"
  11. "github.com/rancher/os/pkg/log"
  12. "github.com/rancher/os/pkg/util"
  13. )
  14. func BootstrapMain() {
  15. log.InitLogger()
  16. log.Debugf("bootstrapAction")
  17. if err := UdevSettle(); err != nil {
  18. log.Errorf("Failed to run udev settle: %v", err)
  19. }
  20. log.Debugf("bootstrapAction: loadingConfig")
  21. cfg := config.LoadConfig()
  22. log.Debugf("bootstrapAction: Rngd(%v)", cfg.Rancher.State.Rngd)
  23. if cfg.Rancher.State.Rngd {
  24. if err := runRngd(); err != nil {
  25. log.Errorf("Failed to run rngd: %v", err)
  26. }
  27. }
  28. log.Debugf("bootstrapAction: MdadmScan(%v)", cfg.Rancher.State.MdadmScan)
  29. if cfg.Rancher.State.MdadmScan {
  30. if err := mdadmScan(); err != nil {
  31. log.Errorf("Failed to run mdadm scan: %v", err)
  32. }
  33. }
  34. log.Debugf("bootstrapAction: cryptsetup(%v)", cfg.Rancher.State.Cryptsetup)
  35. if cfg.Rancher.State.Cryptsetup {
  36. if err := cryptsetup(); err != nil {
  37. log.Errorf("Failed to run cryptsetup: %v", err)
  38. }
  39. }
  40. log.Debugf("bootstrapAction: LvmScan(%v)", cfg.Rancher.State.LvmScan)
  41. if cfg.Rancher.State.LvmScan {
  42. if err := vgchange(); err != nil {
  43. log.Errorf("Failed to run vgchange: %v", err)
  44. }
  45. }
  46. stateScript := cfg.Rancher.State.Script
  47. log.Debugf("bootstrapAction: stateScript(%v)", stateScript)
  48. if stateScript != "" {
  49. if err := runStateScript(stateScript); err != nil {
  50. log.Errorf("Failed to run state script: %v", err)
  51. }
  52. }
  53. log.Debugf("bootstrapAction: RunCommandSequence(%v)", cfg.Bootcmd)
  54. err := util.RunCommandSequence(cfg.Bootcmd)
  55. if err != nil {
  56. log.Error(err)
  57. }
  58. if cfg.Rancher.State.Dev != "" && cfg.Rancher.State.Wait {
  59. waitForRoot(cfg)
  60. }
  61. if len(cfg.Rancher.State.Autoformat) > 0 {
  62. log.Infof("bootstrap container: Autoformat(%v) as %s", cfg.Rancher.State.Autoformat, "ext4")
  63. if err := autoformat(cfg.Rancher.State.Autoformat); err != nil {
  64. log.Errorf("Failed to run autoformat: %v", err)
  65. }
  66. }
  67. log.Debugf("bootstrapAction: udev settle2")
  68. if err := UdevSettle(); err != nil {
  69. log.Errorf("Failed to run udev settle: %v", err)
  70. }
  71. }
  72. func mdadmScan() error {
  73. cmd := exec.Command("mdadm", "--assemble", "--scan")
  74. cmd.Stdout = os.Stdout
  75. cmd.Stderr = os.Stderr
  76. return cmd.Run()
  77. }
  78. func vgchange() error {
  79. cmd := exec.Command("vgchange", "--activate", "ay")
  80. cmd.Stdout = os.Stdout
  81. cmd.Stderr = os.Stderr
  82. return cmd.Run()
  83. }
  84. func cryptsetup() error {
  85. devices, err := util.BlkidType("crypto_LUKS")
  86. if err != nil {
  87. return err
  88. }
  89. for _, cryptdevice := range devices {
  90. fdRead, err := os.Open("/dev/console")
  91. if err != nil {
  92. return err
  93. }
  94. defer fdRead.Close()
  95. fdWrite, err := os.OpenFile("/dev/console", os.O_WRONLY|os.O_APPEND, 0)
  96. if err != nil {
  97. return err
  98. }
  99. defer fdWrite.Close()
  100. cmd := exec.Command("cryptsetup", "luksOpen", cryptdevice, fmt.Sprintf("luks-%s", filepath.Base(cryptdevice)))
  101. cmd.Stdout = fdWrite
  102. cmd.Stderr = fdWrite
  103. cmd.Stdin = fdRead
  104. if err := cmd.Run(); err != nil {
  105. log.Errorf("Failed to run cryptsetup for %s: %v", cryptdevice, err)
  106. }
  107. }
  108. return nil
  109. }
  110. func runRngd() error {
  111. // use /dev/urandom as random number input for rngd
  112. // this is a really bad idea
  113. // since I am simple filling the kernel entropy pool with entropy coming from the kernel itself!
  114. // but this does not need to consider the user's hw rngd drivers.
  115. cmd := exec.Command("rngd", "-r", "/dev/urandom", "-q")
  116. cmd.Stdout = os.Stdout
  117. cmd.Stderr = os.Stderr
  118. return cmd.Run()
  119. }
  120. func runStateScript(script string) error {
  121. f, err := ioutil.TempFile("", "")
  122. if err != nil {
  123. return err
  124. }
  125. if _, err := f.WriteString(script); err != nil {
  126. return err
  127. }
  128. if err := f.Chmod(os.ModePerm); err != nil {
  129. return err
  130. }
  131. if err := f.Close(); err != nil {
  132. return err
  133. }
  134. return util.RunScript(f.Name())
  135. }
  136. func waitForRoot(cfg *config.CloudConfig) {
  137. var dev string
  138. for i := 0; i < 30; i++ {
  139. dev = util.ResolveDevice(cfg.Rancher.State.Dev)
  140. if dev != "" {
  141. break
  142. }
  143. time.Sleep(time.Millisecond * 1000)
  144. }
  145. if dev == "" {
  146. return
  147. }
  148. for i := 0; i < 30; i++ {
  149. if _, err := os.Stat(dev); err == nil {
  150. break
  151. }
  152. time.Sleep(time.Millisecond * 1000)
  153. }
  154. }
  155. func autoformat(autoformatDevices []string) error {
  156. cmd := exec.Command("/usr/sbin/auto-format.sh")
  157. cmd.Stdout = os.Stdout
  158. cmd.Stderr = os.Stderr
  159. cmd.Env = []string{
  160. "AUTOFORMAT=" + strings.Join(autoformatDevices, " "),
  161. }
  162. return cmd.Run()
  163. }