root.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package init
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "path"
  7. "strings"
  8. "syscall"
  9. log "github.com/Sirupsen/logrus"
  10. "github.com/docker/docker/pkg/archive"
  11. "github.com/rancher/docker-from-scratch"
  12. "github.com/rancher/os/config"
  13. )
  14. func cleanupTarget(rootfs, targetUsr, usr, usrVer, tmpDir string) (bool, error) {
  15. log.Debugf("Deleting %s", targetUsr)
  16. if err := os.Remove(targetUsr); err != nil && !os.IsNotExist(err) {
  17. log.Errorf("Failed to delete %s, possibly invalid RancherOS state partition: %v", targetUsr, err)
  18. return false, err
  19. }
  20. if err := dockerlaunch.CreateSymlink(usrVer, path.Join(rootfs, "usr")); err != nil {
  21. return false, err
  22. }
  23. log.Debugf("Deleting %s", tmpDir)
  24. if err := os.RemoveAll(tmpDir); err != nil {
  25. // Don't care if this fails
  26. log.Errorf("Failed to cleanup temp directory %s: %v", tmpDir, err)
  27. }
  28. if _, err := os.Stat(usr); err == nil {
  29. return false, nil
  30. }
  31. return true, nil
  32. }
  33. func copyMoveRoot(rootfs string, rmUsr bool) error {
  34. usrVer := fmt.Sprintf("usr-%s", config.VERSION)
  35. usr := path.Join(rootfs, usrVer)
  36. targetUsr := path.Join(rootfs, "usr")
  37. tmpDir := path.Join(rootfs, "tmp")
  38. if rmUsr {
  39. log.Warnf("Development setup. Removing old usr: %s", usr)
  40. if err := os.RemoveAll(usr); err != nil {
  41. // Don't care if this fails
  42. log.Errorf("Failed to remove %s: %v", usr, err)
  43. }
  44. }
  45. if cont, err := cleanupTarget(rootfs, targetUsr, usr, usrVer, tmpDir); !cont {
  46. return err
  47. }
  48. log.Debugf("Creating temp dir directory %s", tmpDir)
  49. if err := os.MkdirAll(tmpDir, 0755); err != nil {
  50. return err
  51. }
  52. usrVerTmp, err := ioutil.TempDir(tmpDir, usrVer)
  53. if err != nil {
  54. return err
  55. }
  56. log.Debugf("Copying to temp dir %s", usrVerTmp)
  57. if err := archive.CopyWithTar("/usr", usrVerTmp); err != nil {
  58. return err
  59. }
  60. log.Debugf("Renaming %s => %s", usrVerTmp, usr)
  61. if err := os.Rename(usrVerTmp, usr); err != nil {
  62. return err
  63. }
  64. files, err := ioutil.ReadDir("/")
  65. if err != nil {
  66. return err
  67. }
  68. for _, file := range files {
  69. filename := path.Join("/", file.Name())
  70. if filename == rootfs || strings.HasPrefix(rootfs, filename+"/") {
  71. log.Debugf("Skipping Deleting %s", filename)
  72. continue
  73. }
  74. log.Debugf("Deleting %s", filename)
  75. if err := os.RemoveAll(filename); err != nil {
  76. return err
  77. }
  78. }
  79. return nil
  80. }
  81. func switchRoot(rootfs, subdir string, rmUsr bool) error {
  82. if err := syscall.Unmount(config.OEM, 0); err != nil {
  83. log.Debugf("Not umounting OEM: %v", err)
  84. }
  85. if subdir != "" {
  86. fullRootfs := path.Join(rootfs, subdir)
  87. if _, err := os.Stat(fullRootfs); os.IsNotExist(err) {
  88. if err := os.MkdirAll(fullRootfs, 0755); err != nil {
  89. log.Errorf("Failed to create directory %s: %v", fullRootfs, err)
  90. return err
  91. }
  92. }
  93. log.Debugf("Bind mounting mount %s to %s", fullRootfs, rootfs)
  94. if err := syscall.Mount(fullRootfs, rootfs, "", syscall.MS_BIND, ""); err != nil {
  95. log.Errorf("Failed to bind mount subdir for %s: %v", fullRootfs, err)
  96. return err
  97. }
  98. }
  99. for _, i := range []string{"/dev", "/sys", "/proc", "/run"} {
  100. log.Debugf("Moving mount %s to %s", i, path.Join(rootfs, i))
  101. if err := os.MkdirAll(path.Join(rootfs, i), 0755); err != nil {
  102. return err
  103. }
  104. if err := syscall.Mount(i, path.Join(rootfs, i), "", syscall.MS_MOVE, ""); err != nil {
  105. return err
  106. }
  107. }
  108. if err := copyMoveRoot(rootfs, rmUsr); err != nil {
  109. return err
  110. }
  111. log.Debugf("chdir %s", rootfs)
  112. if err := syscall.Chdir(rootfs); err != nil {
  113. return err
  114. }
  115. log.Debugf("mount MS_MOVE %s", rootfs)
  116. if err := syscall.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil {
  117. return err
  118. }
  119. log.Debug("chroot .")
  120. if err := syscall.Chroot("."); err != nil {
  121. return err
  122. }
  123. log.Debug("chdir /")
  124. if err := syscall.Chdir("/"); err != nil {
  125. return err
  126. }
  127. log.Debugf("Successfully moved to new root at %s", path.Join(rootfs, subdir))
  128. os.Unsetenv("DOCKER_RAMDISK")
  129. return nil
  130. }