2016-06-06 22:13:15 +00:00
|
|
|
package control
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2016-06-28 18:18:26 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
2016-06-06 22:13:15 +00:00
|
|
|
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
|
|
|
|
"github.com/codegangsta/cli"
|
|
|
|
composeConfig "github.com/docker/libcompose/config"
|
|
|
|
"github.com/docker/libcompose/project/options"
|
2016-11-29 00:36:23 +00:00
|
|
|
"github.com/rancher/os/cmd/control/service"
|
2016-06-06 22:13:15 +00:00
|
|
|
"github.com/rancher/os/compose"
|
|
|
|
"github.com/rancher/os/config"
|
2016-11-23 10:49:35 +00:00
|
|
|
"github.com/rancher/os/log"
|
2016-11-29 00:36:23 +00:00
|
|
|
"github.com/rancher/os/util"
|
2016-06-06 22:13:15 +00:00
|
|
|
"github.com/rancher/os/util/network"
|
|
|
|
)
|
|
|
|
|
|
|
|
func consoleSubcommands() []cli.Command {
|
|
|
|
return []cli.Command{
|
|
|
|
{
|
|
|
|
Name: "switch",
|
2016-06-13 05:28:24 +00:00
|
|
|
Usage: "switch console without a reboot",
|
2016-06-06 22:13:15 +00:00
|
|
|
Action: consoleSwitch,
|
2016-06-08 05:16:23 +00:00
|
|
|
Flags: []cli.Flag{
|
|
|
|
cli.BoolFlag{
|
|
|
|
Name: "force, f",
|
|
|
|
Usage: "do not prompt for input",
|
|
|
|
},
|
2016-07-21 17:25:32 +00:00
|
|
|
cli.BoolFlag{
|
|
|
|
Name: "no-pull",
|
|
|
|
Usage: "don't pull console image",
|
|
|
|
},
|
2016-06-08 05:16:23 +00:00
|
|
|
},
|
2016-06-06 22:13:15 +00:00
|
|
|
},
|
2016-06-13 05:28:24 +00:00
|
|
|
{
|
|
|
|
Name: "enable",
|
|
|
|
Usage: "set console to be switched on next reboot",
|
|
|
|
Action: consoleEnable,
|
|
|
|
},
|
2016-06-06 22:13:15 +00:00
|
|
|
{
|
|
|
|
Name: "list",
|
|
|
|
Usage: "list available consoles",
|
|
|
|
Action: consoleList,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func consoleSwitch(c *cli.Context) error {
|
|
|
|
if len(c.Args()) != 1 {
|
2016-06-13 05:28:24 +00:00
|
|
|
log.Fatal("Must specify exactly one console to switch to")
|
2016-06-06 22:13:15 +00:00
|
|
|
}
|
|
|
|
newConsole := c.Args()[0]
|
|
|
|
|
2016-06-16 16:52:02 +00:00
|
|
|
cfg := config.LoadConfig()
|
2016-11-29 00:36:23 +00:00
|
|
|
validateConsole(newConsole, cfg)
|
2016-06-29 07:52:38 +00:00
|
|
|
if newConsole == currentConsole() {
|
2016-06-16 16:52:02 +00:00
|
|
|
log.Warnf("Console is already set to %s", newConsole)
|
|
|
|
}
|
|
|
|
|
2016-06-08 05:16:23 +00:00
|
|
|
if !c.Bool("force") {
|
2016-06-30 21:02:04 +00:00
|
|
|
fmt.Println(`Switching consoles will
|
|
|
|
1. destroy the current console container
|
|
|
|
2. log you out
|
|
|
|
3. restart Docker`)
|
2016-10-12 12:41:52 +00:00
|
|
|
if !yes("Continue") {
|
2016-06-08 05:16:23 +00:00
|
|
|
return nil
|
|
|
|
}
|
2016-06-06 22:13:15 +00:00
|
|
|
}
|
|
|
|
|
2016-07-21 17:25:32 +00:00
|
|
|
if !c.Bool("no-pull") && newConsole != "default" {
|
2016-06-12 19:02:07 +00:00
|
|
|
if err := compose.StageServices(cfg, newConsole); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-06-06 22:13:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
service, err := compose.CreateService(nil, "switch-console", &composeConfig.ServiceConfigV1{
|
|
|
|
LogDriver: "json-file",
|
|
|
|
Privileged: true,
|
|
|
|
Net: "host",
|
|
|
|
Pid: "host",
|
2016-11-28 08:06:00 +00:00
|
|
|
Image: config.OsBase,
|
2016-06-06 22:13:15 +00:00
|
|
|
Labels: map[string]string{
|
2016-11-28 08:06:00 +00:00
|
|
|
config.ScopeLabel: config.System,
|
2016-06-06 22:13:15 +00:00
|
|
|
},
|
2016-10-20 18:58:34 +00:00
|
|
|
Command: []string{"/usr/bin/ros", "switch-console", newConsole},
|
2016-06-06 22:13:15 +00:00
|
|
|
VolumesFrom: []string{"all-volumes"},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = service.Delete(context.Background(), options.Delete{}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-06-12 19:02:07 +00:00
|
|
|
if err = service.Up(context.Background(), options.Up{}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return service.Log(context.Background(), true)
|
2016-06-06 22:13:15 +00:00
|
|
|
}
|
|
|
|
|
2016-06-13 05:28:24 +00:00
|
|
|
func consoleEnable(c *cli.Context) error {
|
|
|
|
if len(c.Args()) != 1 {
|
|
|
|
log.Fatal("Must specify exactly one console to enable")
|
|
|
|
}
|
|
|
|
newConsole := c.Args()[0]
|
|
|
|
|
|
|
|
cfg := config.LoadConfig()
|
2016-11-29 00:36:23 +00:00
|
|
|
validateConsole(newConsole, cfg)
|
2016-06-13 05:28:24 +00:00
|
|
|
|
|
|
|
if newConsole != "default" {
|
|
|
|
if err := compose.StageServices(cfg, newConsole); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := config.Set("rancher.console", newConsole); err != nil {
|
|
|
|
log.Errorf("Failed to update 'rancher.console': %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-06-06 22:13:15 +00:00
|
|
|
func consoleList(c *cli.Context) error {
|
|
|
|
cfg := config.LoadConfig()
|
2016-11-29 00:36:23 +00:00
|
|
|
consoles := availableConsoles(cfg)
|
2016-06-29 07:52:38 +00:00
|
|
|
currentConsole := currentConsole()
|
2016-06-06 22:13:15 +00:00
|
|
|
|
|
|
|
for _, console := range consoles {
|
2016-06-28 18:18:26 +00:00
|
|
|
if console == currentConsole {
|
|
|
|
fmt.Printf("current %s\n", console)
|
|
|
|
} else if console == cfg.Rancher.Console {
|
|
|
|
fmt.Printf("enabled %s\n", console)
|
|
|
|
} else {
|
|
|
|
fmt.Printf("disabled %s\n", console)
|
|
|
|
}
|
2016-06-06 22:13:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2016-06-29 07:52:38 +00:00
|
|
|
|
2016-11-29 00:36:23 +00:00
|
|
|
func validateConsole(console string, cfg *config.CloudConfig) {
|
|
|
|
consoles := availableConsoles(cfg)
|
|
|
|
if !service.IsLocalOrURL(console) && !util.Contains(consoles, console) {
|
|
|
|
log.Fatalf("%s is not a valid console", console)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func availableConsoles(cfg *config.CloudConfig) []string {
|
|
|
|
consoles, err := network.GetConsoles(cfg.Rancher.Repositories.ToArray())
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
consoles = append(consoles, "default")
|
|
|
|
sort.Strings(consoles)
|
|
|
|
return consoles
|
|
|
|
}
|
|
|
|
|
2016-06-29 07:52:38 +00:00
|
|
|
func currentConsole() (console string) {
|
|
|
|
consoleBytes, err := ioutil.ReadFile("/run/console-done")
|
|
|
|
if err == nil {
|
|
|
|
console = strings.TrimSpace(string(consoleBytes))
|
|
|
|
} else {
|
|
|
|
log.Warnf("Failed to detect current console: %v", err)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|