console.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package control
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "sort"
  8. "strings"
  9. "golang.org/x/net/context"
  10. log "github.com/Sirupsen/logrus"
  11. "github.com/codegangsta/cli"
  12. composeConfig "github.com/docker/libcompose/config"
  13. "github.com/docker/libcompose/project/options"
  14. "github.com/rancher/os/compose"
  15. "github.com/rancher/os/config"
  16. "github.com/rancher/os/util/network"
  17. )
  18. func consoleSubcommands() []cli.Command {
  19. return []cli.Command{
  20. {
  21. Name: "switch",
  22. Usage: "switch console without a reboot",
  23. Action: consoleSwitch,
  24. Flags: []cli.Flag{
  25. cli.BoolFlag{
  26. Name: "force, f",
  27. Usage: "do not prompt for input",
  28. },
  29. cli.BoolFlag{
  30. Name: "no-pull",
  31. Usage: "don't pull console image",
  32. },
  33. },
  34. },
  35. {
  36. Name: "enable",
  37. Usage: "set console to be switched on next reboot",
  38. Action: consoleEnable,
  39. },
  40. {
  41. Name: "list",
  42. Usage: "list available consoles",
  43. Action: consoleList,
  44. },
  45. }
  46. }
  47. func consoleSwitch(c *cli.Context) error {
  48. if len(c.Args()) != 1 {
  49. log.Fatal("Must specify exactly one console to switch to")
  50. }
  51. newConsole := c.Args()[0]
  52. cfg := config.LoadConfig()
  53. if newConsole == currentConsole() {
  54. log.Warnf("Console is already set to %s", newConsole)
  55. }
  56. if !c.Bool("force") {
  57. in := bufio.NewReader(os.Stdin)
  58. fmt.Println(`Switching consoles will
  59. 1. destroy the current console container
  60. 2. log you out
  61. 3. restart Docker`)
  62. if !yes(in, "Continue") {
  63. return nil
  64. }
  65. }
  66. if !c.Bool("no-pull") && newConsole != "default" {
  67. if err := compose.StageServices(cfg, newConsole); err != nil {
  68. return err
  69. }
  70. }
  71. service, err := compose.CreateService(nil, "switch-console", &composeConfig.ServiceConfigV1{
  72. LogDriver: "json-file",
  73. Privileged: true,
  74. Net: "host",
  75. Pid: "host",
  76. Image: config.OS_BASE,
  77. Labels: map[string]string{
  78. config.SCOPE: config.SYSTEM,
  79. },
  80. Command: []string{"/usr/bin/switch-console", newConsole},
  81. VolumesFrom: []string{"all-volumes"},
  82. })
  83. if err != nil {
  84. return err
  85. }
  86. if err = service.Delete(context.Background(), options.Delete{}); err != nil {
  87. return err
  88. }
  89. if err = service.Up(context.Background(), options.Up{}); err != nil {
  90. return err
  91. }
  92. return service.Log(context.Background(), true)
  93. }
  94. func consoleEnable(c *cli.Context) error {
  95. if len(c.Args()) != 1 {
  96. log.Fatal("Must specify exactly one console to enable")
  97. }
  98. newConsole := c.Args()[0]
  99. cfg := config.LoadConfig()
  100. if newConsole != "default" {
  101. if err := compose.StageServices(cfg, newConsole); err != nil {
  102. return err
  103. }
  104. }
  105. if err := config.Set("rancher.console", newConsole); err != nil {
  106. log.Errorf("Failed to update 'rancher.console': %v", err)
  107. }
  108. return nil
  109. }
  110. func consoleList(c *cli.Context) error {
  111. cfg := config.LoadConfig()
  112. consoles, err := network.GetConsoles(cfg.Rancher.Repositories.ToArray())
  113. if err != nil {
  114. return err
  115. }
  116. consoles = append(consoles, "default")
  117. sort.Strings(consoles)
  118. currentConsole := currentConsole()
  119. for _, console := range consoles {
  120. if console == currentConsole {
  121. fmt.Printf("current %s\n", console)
  122. } else if console == cfg.Rancher.Console {
  123. fmt.Printf("enabled %s\n", console)
  124. } else {
  125. fmt.Printf("disabled %s\n", console)
  126. }
  127. }
  128. return nil
  129. }
  130. func currentConsole() (console string) {
  131. consoleBytes, err := ioutil.ReadFile("/run/console-done")
  132. if err == nil {
  133. console = strings.TrimSpace(string(consoleBytes))
  134. } else {
  135. log.Warnf("Failed to detect current console: %v", err)
  136. }
  137. return
  138. }