mirror of
https://github.com/rancher/os.git
synced 2025-09-03 15:54:24 +00:00
Merge pull request #1931 from SvenDowideit/autologin-and-recovery-console
WIP Autologin and recovery console
This commit is contained in:
103
cmd/control/autologin.go
Normal file
103
cmd/control/autologin.go
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
"github.com/rancher/os/config"
|
||||||
|
"github.com/rancher/os/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AutologinMain() {
|
||||||
|
log.InitLogger()
|
||||||
|
app := cli.NewApp()
|
||||||
|
|
||||||
|
app.Name = os.Args[0]
|
||||||
|
app.Usage = "autologin console"
|
||||||
|
app.Version = config.Version
|
||||||
|
app.Author = "Rancher Labs, Inc."
|
||||||
|
app.Email = "sven@rancher.com"
|
||||||
|
app.EnableBashCompletion = true
|
||||||
|
app.Action = autologinAction
|
||||||
|
app.HideHelp = true
|
||||||
|
app.Run(os.Args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autologinAction(c *cli.Context) error {
|
||||||
|
cmd := exec.Command("/bin/stty", "sane")
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
usertty := ""
|
||||||
|
user := "root"
|
||||||
|
tty := ""
|
||||||
|
if c.NArg() > 0 {
|
||||||
|
usertty = c.Args().Get(0)
|
||||||
|
s := strings.SplitN(usertty, ":", 2)
|
||||||
|
user = s[0]
|
||||||
|
if len(s) > 1 {
|
||||||
|
tty = s[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mode := filepath.Base(os.Args[0])
|
||||||
|
console := CurrentConsole()
|
||||||
|
|
||||||
|
cfg := config.LoadConfig()
|
||||||
|
// replace \n and \l
|
||||||
|
banner := config.Banner
|
||||||
|
banner = strings.Replace(banner, "\\v", config.Version, -1)
|
||||||
|
banner = strings.Replace(banner, "\\s", "RancherOS "+runtime.GOARCH, -1)
|
||||||
|
banner = strings.Replace(banner, "\\r", config.GetKernelVersion(), -1)
|
||||||
|
banner = strings.Replace(banner, "\\n", cfg.Hostname, -1)
|
||||||
|
banner = strings.Replace(banner, "\\l", tty, -1)
|
||||||
|
banner = strings.Replace(banner, "\\\\", "\\", -1)
|
||||||
|
banner = banner + "\n"
|
||||||
|
banner = banner + "Autologin " + console + "\n"
|
||||||
|
fmt.Printf(banner)
|
||||||
|
|
||||||
|
loginBin := ""
|
||||||
|
args := []string{}
|
||||||
|
if console == "centos" || console == "fedora" ||
|
||||||
|
mode == "recovery" {
|
||||||
|
// For some reason, centos and fedora ttyS0 and tty1 don't work with `login -f rancher`
|
||||||
|
// until I make time to read their source, lets just give us a way to get work done
|
||||||
|
loginBin = "bash"
|
||||||
|
args = append(args, "--login")
|
||||||
|
os.Setenv("PROMPT_COMMAND", `echo "[`+fmt.Sprintf("Recovery console %s@%s:${PWD}", user, cfg.Hostname)+`]"`)
|
||||||
|
} else {
|
||||||
|
loginBin = "login"
|
||||||
|
args = append(args, "-f", user)
|
||||||
|
// TODO: add a PROMPT_COMMAND if we haven't switch-rooted
|
||||||
|
}
|
||||||
|
|
||||||
|
loginBinPath, err := exec.LookPath(loginBin)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("error finding %s in path: %s", cmd.Args[0], err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
os.Setenv("TERM", "linux")
|
||||||
|
|
||||||
|
// Causes all sorts of issues
|
||||||
|
//return syscall.Exec(loginBinPath, args, os.Environ())
|
||||||
|
cmd = exec.Command(loginBinPath, args...)
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
cmd.Env = append(cmd.Env, "SVEN", "MORE")
|
||||||
|
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
log.Errorf("\nError starting %s: %s", cmd.Args[0], err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@@ -101,6 +101,13 @@ func Main() {
|
|||||||
SkipFlagParsing: true,
|
SkipFlagParsing: true,
|
||||||
Action: preloadImagesAction,
|
Action: preloadImagesAction,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "recovery-init",
|
||||||
|
Hidden: true,
|
||||||
|
HideHelp: true,
|
||||||
|
SkipFlagParsing: true,
|
||||||
|
Action: recoveryInitAction,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "switch-console",
|
Name: "switch-console",
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
|
@@ -225,7 +225,15 @@ func merge(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = config.Merge(bytes); err != nil {
|
if err = config.Merge(bytes); err != nil {
|
||||||
log.Fatal(err)
|
log.Error(err)
|
||||||
|
validationErrors, err := config.ValidateBytes(bytes)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, validationError := range validationErrors.Errors() {
|
||||||
|
log.Error(validationError)
|
||||||
|
}
|
||||||
|
log.Fatal("EXITING: Failed to parse configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -255,7 +263,7 @@ func validate(c *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
validationErrors, err := config.Validate(bytes)
|
validationErrors, err := config.ValidateBytes(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@@ -2,18 +2,19 @@ package control
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
|
"github.com/docker/docker/reference"
|
||||||
composeConfig "github.com/docker/libcompose/config"
|
composeConfig "github.com/docker/libcompose/config"
|
||||||
"github.com/docker/libcompose/project/options"
|
"github.com/docker/libcompose/project/options"
|
||||||
"github.com/rancher/os/cmd/control/service"
|
"github.com/rancher/os/cmd/control/service"
|
||||||
"github.com/rancher/os/compose"
|
"github.com/rancher/os/compose"
|
||||||
"github.com/rancher/os/config"
|
"github.com/rancher/os/config"
|
||||||
|
"github.com/rancher/os/docker"
|
||||||
"github.com/rancher/os/log"
|
"github.com/rancher/os/log"
|
||||||
"github.com/rancher/os/util"
|
"github.com/rancher/os/util"
|
||||||
"github.com/rancher/os/util/network"
|
"github.com/rancher/os/util/network"
|
||||||
@@ -57,7 +58,7 @@ func consoleSwitch(c *cli.Context) error {
|
|||||||
|
|
||||||
cfg := config.LoadConfig()
|
cfg := config.LoadConfig()
|
||||||
validateConsole(newConsole, cfg)
|
validateConsole(newConsole, cfg)
|
||||||
if newConsole == currentConsole() {
|
if newConsole == CurrentConsole() {
|
||||||
log.Warnf("Console is already set to %s", newConsole)
|
log.Warnf("Console is already set to %s", newConsole)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,10 +128,10 @@ func consoleEnable(c *cli.Context) error {
|
|||||||
func consoleList(c *cli.Context) error {
|
func consoleList(c *cli.Context) error {
|
||||||
cfg := config.LoadConfig()
|
cfg := config.LoadConfig()
|
||||||
consoles := availableConsoles(cfg)
|
consoles := availableConsoles(cfg)
|
||||||
currentConsole := currentConsole()
|
CurrentConsole := CurrentConsole()
|
||||||
|
|
||||||
for _, console := range consoles {
|
for _, console := range consoles {
|
||||||
if console == currentConsole {
|
if console == CurrentConsole {
|
||||||
fmt.Printf("current %s\n", console)
|
fmt.Printf("current %s\n", console)
|
||||||
} else if console == cfg.Rancher.Console {
|
} else if console == cfg.Rancher.Console {
|
||||||
fmt.Printf("enabled %s\n", console)
|
fmt.Printf("enabled %s\n", console)
|
||||||
@@ -159,12 +160,32 @@ func availableConsoles(cfg *config.CloudConfig) []string {
|
|||||||
return consoles
|
return consoles
|
||||||
}
|
}
|
||||||
|
|
||||||
func currentConsole() (console string) {
|
// CurrentConsole gets the name of the console that's running
|
||||||
consoleBytes, err := ioutil.ReadFile("/run/console-done")
|
func CurrentConsole() (console string) {
|
||||||
if err == nil {
|
// TODO: replace this docker container look up with a libcompose service lookup?
|
||||||
console = strings.TrimSpace(string(consoleBytes))
|
|
||||||
} else {
|
// sudo system-docker inspect --format "{{.Config.Image}}" console
|
||||||
|
client, err := docker.NewSystemClient()
|
||||||
|
if err != nil {
|
||||||
log.Warnf("Failed to detect current console: %v", err)
|
log.Warnf("Failed to detect current console: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
info, err := client.ContainerInspect(context.Background(), "console")
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to detect current console: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// parse image name, then remove os- prefix and the console suffix
|
||||||
|
image, err := reference.ParseNamed(info.Config.Image)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to detect current console(%s): %v", info.Config.Image, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(image.Name(), "os-console") {
|
||||||
|
console = "default"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console = strings.TrimPrefix(strings.TrimSuffix(image.Name(), "console"), "rancher/os-")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/SvenDowideit/cpuid"
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/rancher/os/cmd/cloudinitexecute"
|
"github.com/rancher/os/cmd/cloudinitexecute"
|
||||||
"github.com/rancher/os/config"
|
"github.com/rancher/os/config"
|
||||||
@@ -82,7 +81,7 @@ func consoleInitFunc() error {
|
|||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := writeRespawn(); err != nil {
|
if err := writeRespawn("rancher", cfg.Rancher.SSH.Daemon, false); err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,17 +108,7 @@ func consoleInitFunc() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// font backslashes need to be escaped for when issue is output! (but not the others..)
|
// font backslashes need to be escaped for when issue is output! (but not the others..)
|
||||||
if err := ioutil.WriteFile("/etc/issue", []byte(`
|
if err := ioutil.WriteFile("/etc/issue", []byte(config.Banner), 0644); err != nil {
|
||||||
, , ______ _ _____ _____TM
|
|
||||||
,------------|'------'| | ___ \\ | | / _ / ___|
|
|
||||||
/ . '-' |- | |_/ /__ _ _ __ ___| |__ ___ _ __ | | | \\ '--.
|
|
||||||
\\/| | | | // _' | '_ \\ / __| '_ \\ / _ \\ '__' | | | |'--. \\
|
|
||||||
| .________.'----' | |\\ \\ (_| | | | | (__| | | | __/ | | \\_/ /\\__/ /
|
|
||||||
| | | | \\_| \\_\\__,_|_| |_|\\___|_| |_|\\___|_| \\___/\\____/
|
|
||||||
\\___/ \\___/ \s \r
|
|
||||||
|
|
||||||
RancherOS `+config.Version+` \n \l `+cpuid.CPU.HypervisorName+`
|
|
||||||
`), 0644); err != nil {
|
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +126,7 @@ func consoleInitFunc() error {
|
|||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(consoleDone, []byte(cfg.Rancher.Console), 0644); err != nil {
|
if err := ioutil.WriteFile(consoleDone, []byte(CurrentConsole()), 0644); err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,15 +144,20 @@ func consoleInitFunc() error {
|
|||||||
return syscall.Exec(respawnBinPath, []string{"respawn", "-f", "/etc/respawn.conf"}, os.Environ())
|
return syscall.Exec(respawnBinPath, []string{"respawn", "-f", "/etc/respawn.conf"}, os.Environ())
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateRespawnConf(cmdline string) string {
|
func generateRespawnConf(cmdline, user string, sshd, recovery bool) string {
|
||||||
var respawnConf bytes.Buffer
|
var respawnConf bytes.Buffer
|
||||||
|
|
||||||
|
autologinBin := "/usr/bin/autologin"
|
||||||
|
if recovery {
|
||||||
|
autologinBin = "/usr/bin/recovery"
|
||||||
|
}
|
||||||
|
|
||||||
for i := 1; i < 7; i++ {
|
for i := 1; i < 7; i++ {
|
||||||
tty := fmt.Sprintf("tty%d", i)
|
tty := fmt.Sprintf("tty%d", i)
|
||||||
|
|
||||||
respawnConf.WriteString(gettyCmd)
|
respawnConf.WriteString(gettyCmd)
|
||||||
if strings.Contains(cmdline, fmt.Sprintf("rancher.autologin=%s", tty)) {
|
if strings.Contains(cmdline, fmt.Sprintf("rancher.autologin=%s", tty)) {
|
||||||
respawnConf.WriteString(" --autologin rancher")
|
respawnConf.WriteString(fmt.Sprintf(" -n -l %s -o %s:tty%d", autologinBin, user, i))
|
||||||
}
|
}
|
||||||
respawnConf.WriteString(fmt.Sprintf(" --noclear %s linux\n", tty))
|
respawnConf.WriteString(fmt.Sprintf(" --noclear %s linux\n", tty))
|
||||||
}
|
}
|
||||||
@@ -175,23 +169,25 @@ func generateRespawnConf(cmdline string) string {
|
|||||||
|
|
||||||
respawnConf.WriteString(gettyCmd)
|
respawnConf.WriteString(gettyCmd)
|
||||||
if strings.Contains(cmdline, fmt.Sprintf("rancher.autologin=%s", tty)) {
|
if strings.Contains(cmdline, fmt.Sprintf("rancher.autologin=%s", tty)) {
|
||||||
respawnConf.WriteString(" --autologin rancher")
|
respawnConf.WriteString(fmt.Sprintf(" -n -l %s -o %s:%s", autologinBin, user, tty))
|
||||||
}
|
}
|
||||||
respawnConf.WriteString(fmt.Sprintf(" %s\n", tty))
|
respawnConf.WriteString(fmt.Sprintf(" %s\n", tty))
|
||||||
}
|
}
|
||||||
|
|
||||||
respawnConf.WriteString("/usr/sbin/sshd -D")
|
if sshd {
|
||||||
|
respawnConf.WriteString("/usr/sbin/sshd -D")
|
||||||
|
}
|
||||||
|
|
||||||
return respawnConf.String()
|
return respawnConf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeRespawn() error {
|
func writeRespawn(user string, sshd, recovery bool) error {
|
||||||
cmdline, err := ioutil.ReadFile("/proc/cmdline")
|
cmdline, err := ioutil.ReadFile("/proc/cmdline")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
respawn := generateRespawnConf(string(cmdline))
|
respawn := generateRespawnConf(string(cmdline), user, sshd, recovery)
|
||||||
|
|
||||||
files, err := ioutil.ReadDir("/etc/respawn.conf.d")
|
files, err := ioutil.ReadDir("/etc/respawn.conf.d")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/rancher/os/config"
|
|
||||||
"github.com/rancher/os/log"
|
"github.com/rancher/os/log"
|
||||||
"github.com/rancher/os/util"
|
"github.com/rancher/os/util"
|
||||||
)
|
)
|
||||||
@@ -22,6 +21,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func dockerInitAction(c *cli.Context) error {
|
func dockerInitAction(c *cli.Context) error {
|
||||||
|
// TODO: this should be replaced by a "Console ready event watcher"
|
||||||
for {
|
for {
|
||||||
if _, err := os.Stat(consoleDone); err == nil {
|
if _, err := os.Stat(consoleDone); err == nil {
|
||||||
break
|
break
|
||||||
@@ -69,9 +69,8 @@ func dockerInitAction(c *cli.Context) error {
|
|||||||
fmt.Sprintf(`[ -e %s ] && source %s; exec /usr/bin/dockerlaunch %s %s $DOCKER_OPTS >> %s 2>&1`, dockerConf, dockerConf, dockerBin, strings.Join(c.Args(), " "), dockerLog),
|
fmt.Sprintf(`[ -e %s ] && source %s; exec /usr/bin/dockerlaunch %s %s $DOCKER_OPTS >> %s 2>&1`, dockerConf, dockerConf, dockerBin, strings.Join(c.Args(), " "), dockerLog),
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := config.LoadConfig()
|
// TODO: this should be replaced by a "Docker ready event watcher"
|
||||||
|
if err := ioutil.WriteFile(dockerDone, []byte(CurrentEngine()), 0644); err != nil {
|
||||||
if err := ioutil.WriteFile(dockerDone, []byte(cfg.Rancher.Docker.Engine), 0644); err != nil {
|
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,17 +2,18 @@ package control
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
|
"github.com/docker/docker/reference"
|
||||||
"github.com/docker/libcompose/project/options"
|
"github.com/docker/libcompose/project/options"
|
||||||
"github.com/rancher/os/cmd/control/service"
|
"github.com/rancher/os/cmd/control/service"
|
||||||
"github.com/rancher/os/compose"
|
"github.com/rancher/os/compose"
|
||||||
"github.com/rancher/os/config"
|
"github.com/rancher/os/config"
|
||||||
|
"github.com/rancher/os/docker"
|
||||||
"github.com/rancher/os/log"
|
"github.com/rancher/os/log"
|
||||||
"github.com/rancher/os/util"
|
"github.com/rancher/os/util"
|
||||||
"github.com/rancher/os/util/network"
|
"github.com/rancher/os/util/network"
|
||||||
@@ -104,7 +105,7 @@ func engineEnable(c *cli.Context) error {
|
|||||||
func engineList(c *cli.Context) error {
|
func engineList(c *cli.Context) error {
|
||||||
cfg := config.LoadConfig()
|
cfg := config.LoadConfig()
|
||||||
engines := availableEngines(cfg)
|
engines := availableEngines(cfg)
|
||||||
currentEngine := currentEngine()
|
currentEngine := CurrentEngine()
|
||||||
|
|
||||||
for _, engine := range engines {
|
for _, engine := range engines {
|
||||||
if engine == currentEngine {
|
if engine == currentEngine {
|
||||||
@@ -135,12 +136,33 @@ func availableEngines(cfg *config.CloudConfig) []string {
|
|||||||
return engines
|
return engines
|
||||||
}
|
}
|
||||||
|
|
||||||
func currentEngine() (engine string) {
|
// CurrentEngine gets the name of the docker that's running
|
||||||
engineBytes, err := ioutil.ReadFile(dockerDone)
|
func CurrentEngine() (engine string) {
|
||||||
if err == nil {
|
// sudo system-docker inspect --format "{{.Config.Image}}" docker
|
||||||
engine = strings.TrimSpace(string(engineBytes))
|
client, err := docker.NewSystemClient()
|
||||||
} else {
|
if err != nil {
|
||||||
log.Warnf("Failed to detect current Docker engine: %v", err)
|
log.Warnf("Failed to detect current docker: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
info, err := client.ContainerInspect(context.Background(), "docker")
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to detect current docker: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// parse image name, then remove os- prefix and the engine suffix
|
||||||
|
image, err := reference.ParseNamed(info.Config.Image)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to detect current docker(%s): %v", info.Config.Image, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if t, ok := image.(reference.NamedTagged); ok {
|
||||||
|
tag := t.Tag()
|
||||||
|
if !strings.HasPrefix(tag, "1.") {
|
||||||
|
// TODO: this assumes we only do Docker ce :/
|
||||||
|
tag = tag + "-ce"
|
||||||
|
}
|
||||||
|
return "docker-" + tag
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -79,6 +79,8 @@ func writeFiles(cfg *config.CloudConfig) error {
|
|||||||
|
|
||||||
func setupCommandSymlinks() {
|
func setupCommandSymlinks() {
|
||||||
for _, link := range []symlink{
|
for _, link := range []symlink{
|
||||||
|
{config.RosBin, "/usr/bin/autologin"},
|
||||||
|
{config.RosBin, "/usr/bin/recovery"},
|
||||||
{config.RosBin, "/usr/bin/cloud-init-execute"},
|
{config.RosBin, "/usr/bin/cloud-init-execute"},
|
||||||
{config.RosBin, "/usr/bin/cloud-init-save"},
|
{config.RosBin, "/usr/bin/cloud-init-save"},
|
||||||
{config.RosBin, "/usr/bin/dockerlaunch"},
|
{config.RosBin, "/usr/bin/dockerlaunch"},
|
||||||
|
23
cmd/control/recovery_init.go
Normal file
23
cmd/control/recovery_init.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func recoveryInitAction(c *cli.Context) error {
|
||||||
|
if err := writeRespawn("root", false, true); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
respawnBinPath, err := exec.LookPath("respawn")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return syscall.Exec(respawnBinPath, []string{"respawn", "-f", "/etc/respawn.conf"}, os.Environ())
|
||||||
|
}
|
@@ -1,10 +1,25 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
yaml "github.com/cloudfoundry-incubator/candiedyaml"
|
yaml "github.com/cloudfoundry-incubator/candiedyaml"
|
||||||
"github.com/rancher/os/util"
|
"github.com/rancher/os/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const Banner = `
|
||||||
|
, , ______ _ _____ _____TM
|
||||||
|
,------------|'------'| | ___ \\ | | / _ / ___|
|
||||||
|
/ . '-' |- | |_/ /__ _ _ __ ___| |__ ___ _ __ | | | \\ '--.
|
||||||
|
\\/| | | | // _' | '_ \\ / __| '_ \\ / _ \\ '__' | | | |'--. \\
|
||||||
|
| .________.'----' | |\\ \\ (_| | | | | (__| | | | __/ | | \\_/ /\\__/ /
|
||||||
|
| | | | \\_| \\_\\__,_|_| |_|\\___|_| |_|\\___|_| \\___/\\____/
|
||||||
|
\\___/ \\___/ \s \r
|
||||||
|
|
||||||
|
RancherOS \v \n \l
|
||||||
|
`
|
||||||
|
|
||||||
func Merge(bytes []byte) error {
|
func Merge(bytes []byte) error {
|
||||||
data, err := readConfigs(bytes, false, true)
|
data, err := readConfigs(bytes, false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -60,3 +75,12 @@ func Set(key string, value interface{}) error {
|
|||||||
|
|
||||||
return WriteToFile(modified, CloudConfigFile)
|
return WriteToFile(modified, CloudConfigFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetKernelVersion() string {
|
||||||
|
b, err := ioutil.ReadFile("/proc/version")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
elem := strings.Split(string(b), " ")
|
||||||
|
return elem[2]
|
||||||
|
}
|
||||||
|
@@ -71,8 +71,19 @@ func LoadConfigWithPrefix(dirPrefix string) *CloudConfig {
|
|||||||
|
|
||||||
cfg := &CloudConfig{}
|
cfg := &CloudConfig{}
|
||||||
if err := util.Convert(rawCfg, cfg); err != nil {
|
if err := util.Convert(rawCfg, cfg); err != nil {
|
||||||
log.Errorf("Failed to parse configuration: %s", err)
|
log.Errorf("EXITING: Failed to parse configuration: %s", err)
|
||||||
log.Debugf("Bad cfg:\n%v\n", rawCfg)
|
log.Debugf("Bad cfg:\n%v\n", rawCfg)
|
||||||
|
// no point returning {}, it'll just sit there broken
|
||||||
|
// TODO: print some context around what failed..
|
||||||
|
validationErrors, err := ValidateRawCfg(rawCfg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, validationError := range validationErrors.Errors() {
|
||||||
|
log.Error(validationError)
|
||||||
|
}
|
||||||
|
// TODO: I'd love to panic & recover(), for issues on boot, but it doesn't work yet
|
||||||
|
os.Exit(-1)
|
||||||
return &CloudConfig{}
|
return &CloudConfig{}
|
||||||
}
|
}
|
||||||
cfg = amendNils(cfg)
|
cfg = amendNils(cfg)
|
||||||
|
@@ -37,6 +37,7 @@ var schema = `{
|
|||||||
"no_sharedroot": {"type": "boolean"},
|
"no_sharedroot": {"type": "boolean"},
|
||||||
"log": {"type": "boolean"},
|
"log": {"type": "boolean"},
|
||||||
"force_console_rebuild": {"type": "boolean"},
|
"force_console_rebuild": {"type": "boolean"},
|
||||||
|
"recovery": {"type": "boolean"},
|
||||||
"disable": {"$ref": "#/definitions/list_of_strings"},
|
"disable": {"$ref": "#/definitions/list_of_strings"},
|
||||||
"services_include": {"type": "object"},
|
"services_include": {"type": "object"},
|
||||||
"modules": {"$ref": "#/definitions/list_of_strings"},
|
"modules": {"$ref": "#/definitions/list_of_strings"},
|
||||||
@@ -144,7 +145,8 @@ var schema = `{
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"keys": {"type": "object"}
|
"keys": {"type": "object"},
|
||||||
|
"daemon": {"type": "boolean"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -113,6 +113,7 @@ type RancherConfig struct {
|
|||||||
NoSharedRoot bool `yaml:"no_sharedroot,omitempty"`
|
NoSharedRoot bool `yaml:"no_sharedroot,omitempty"`
|
||||||
Log bool `yaml:"log,omitempty"`
|
Log bool `yaml:"log,omitempty"`
|
||||||
ForceConsoleRebuild bool `yaml:"force_console_rebuild,omitempty"`
|
ForceConsoleRebuild bool `yaml:"force_console_rebuild,omitempty"`
|
||||||
|
Recovery bool `yaml:"recovery,omitempty"`
|
||||||
Disable []string `yaml:"disable,omitempty"`
|
Disable []string `yaml:"disable,omitempty"`
|
||||||
ServicesInclude map[string]bool `yaml:"services_include,omitempty"`
|
ServicesInclude map[string]bool `yaml:"services_include,omitempty"`
|
||||||
Modules []string `yaml:"modules,omitempty"`
|
Modules []string `yaml:"modules,omitempty"`
|
||||||
@@ -174,7 +175,8 @@ type DockerConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SSHConfig struct {
|
type SSHConfig struct {
|
||||||
Keys map[string]string `yaml:"keys,omitempty"`
|
Keys map[string]string `yaml:"keys,omitempty"`
|
||||||
|
Daemon bool `yaml:"daemon,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type StateConfig struct {
|
type StateConfig struct {
|
||||||
|
@@ -31,11 +31,15 @@ func ConvertKeysToStrings(item interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Validate(bytes []byte) (*gojsonschema.Result, error) {
|
func ValidateBytes(bytes []byte) (*gojsonschema.Result, error) {
|
||||||
var rawCfg map[string]interface{}
|
var rawCfg map[string]interface{}
|
||||||
if err := yaml.Unmarshal([]byte(bytes), &rawCfg); err != nil {
|
if err := yaml.Unmarshal([]byte(bytes), &rawCfg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return ValidateRawCfg(rawCfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateRawCfg(rawCfg interface{}) (*gojsonschema.Result, error) {
|
||||||
rawCfg = ConvertKeysToStrings(rawCfg).(map[string]interface{})
|
rawCfg = ConvertKeysToStrings(rawCfg).(map[string]interface{})
|
||||||
loader := gojsonschema.NewGoLoader(rawCfg)
|
loader := gojsonschema.NewGoLoader(rawCfg)
|
||||||
schemaLoader := gojsonschema.NewStringLoader(schema)
|
schemaLoader := gojsonschema.NewStringLoader(schema)
|
||||||
|
@@ -2,7 +2,6 @@ package docker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
composeConfig "github.com/docker/libcompose/config"
|
composeConfig "github.com/docker/libcompose/config"
|
||||||
@@ -43,11 +42,9 @@ func environmentFromCloudConfig(cfg *config.CloudConfig) map[string]string {
|
|||||||
environment["no_proxy"] = cfg.Rancher.Network.NoProxy
|
environment["no_proxy"] = cfg.Rancher.Network.NoProxy
|
||||||
environment["NO_PROXY"] = cfg.Rancher.Network.NoProxy
|
environment["NO_PROXY"] = cfg.Rancher.Network.NoProxy
|
||||||
}
|
}
|
||||||
b, err := ioutil.ReadFile("/proc/version")
|
if v := config.GetKernelVersion(); v != "" {
|
||||||
if err == nil {
|
environment["KERNEL_VERSION"] = v
|
||||||
elem := strings.Split(string(b), " ")
|
log.Debugf("Using /proc/version to set rancher.environment.KERNEL_VERSION = %s", v)
|
||||||
environment["KERNEL_VERSION"] = elem[2]
|
|
||||||
log.Debugf("Using /proc/version to set rancher.environment.KERNEL_VERSION = %s", elem[2])
|
|
||||||
}
|
}
|
||||||
return environment
|
return environment
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,11 @@ layout: os-default
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Kernel parameters
|
## Kernel boot parameters
|
||||||
|
|
||||||
There are two ways to edit the kernel parameters, in-place (editing the file and reboot) or during installation to disk.
|
RancherOS parses the Linux kernel boot cmdline to add any keys it understands to its configuration. This allows you to modify what cloud-init sources it will use on boot, to enable `rancher.debug` logging, or to almost any other configuration setting.
|
||||||
|
|
||||||
|
There are two ways to set or modify persistent kernel parameters, in-place (editing the file and reboot) or during installation to disk.
|
||||||
|
|
||||||
### In-place editing
|
### In-place editing
|
||||||
|
|
||||||
@@ -14,10 +16,6 @@ To edit the kernel boot parameters of an already installed RancherOS system, use
|
|||||||
|
|
||||||
> To activate this setting, you will need to reboot.
|
> To activate this setting, you will need to reboot.
|
||||||
|
|
||||||
#### Graphical boot screen
|
|
||||||
|
|
||||||
RancherOS v1.1.0 added a syslinux boot menu, which on desktop systems can be switched to graphical mode by adding `UI vesamenu.c32` to a new line in `global.cfg` (use `sudo ros config syslinux` to edit the file).
|
|
||||||
|
|
||||||
### During installation
|
### During installation
|
||||||
|
|
||||||
If you want to set the extra kernel parameters when you are [Installing RancherOS to Disk]({{site.baseurl}}/os/running-rancheros/server/install-to-disk/) please use the `--append` parameter.
|
If you want to set the extra kernel parameters when you are [Installing RancherOS to Disk]({{site.baseurl}}/os/running-rancheros/server/install-to-disk/) please use the `--append` parameter.
|
||||||
@@ -25,3 +23,28 @@ If you want to set the extra kernel parameters when you are [Installing RancherO
|
|||||||
```bash
|
```bash
|
||||||
$ sudo ros install -d /dev/sda --append "rancheros.autologin=tty1"
|
$ sudo ros install -d /dev/sda --append "rancheros.autologin=tty1"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Graphical boot screen
|
||||||
|
|
||||||
|
RancherOS v1.1.0 added a Syslinux boot menu, which allows you to temporarily edit the boot paramters, or to select "Debug logging", "Autologin", both "Debug logging & Autologin" and "Recovery Console".
|
||||||
|
|
||||||
|
|
||||||
|
On desktop systems the Syslinux boot menu can be switched to graphical mode by adding `UI vesamenu.c32` to a new line in `global.cfg` (use `sudo ros config syslinux` to edit the file).
|
||||||
|
|
||||||
|
### Useful RancherOS cloud-init or boot settings
|
||||||
|
|
||||||
|
#### Recovery console
|
||||||
|
|
||||||
|
`rancher.recovery=true` will start a single user `root` bash session as easily in the boot process, with no network, or persitent filesystem mounted. This can be used to fix disk problems, or to debug your system.
|
||||||
|
|
||||||
|
#### Enable/Disable sshd
|
||||||
|
|
||||||
|
`rancher.ssh.daemon=false` (its enabled in the os-config) can be used to start your RancherOS with no sshd daemon. This can be used to futher reduce the ports that your system is listening on.
|
||||||
|
|
||||||
|
#### Enable debug logging
|
||||||
|
|
||||||
|
`rancher.debug=true` will log everything to the console for debugging.
|
||||||
|
|
||||||
|
#### Autologin console
|
||||||
|
|
||||||
|
`rancher.autologin=<tty...>` will automatically log in the sepcified console - common values are `tty1`, `ttyS0` and `ttyAMA0` - depending on your platform.
|
||||||
|
16
init/init.go
16
init/init.go
@@ -94,6 +94,13 @@ func sysInit(c *config.CloudConfig) (*config.CloudConfig, error) {
|
|||||||
|
|
||||||
func MainInit() {
|
func MainInit() {
|
||||||
log.InitDeferedLogger()
|
log.InitDeferedLogger()
|
||||||
|
// TODO: this breaks and does nothing if the cfg is invalid (or is it due to threading?)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
fmt.Printf("Starting Recovery console: %v\n", r)
|
||||||
|
recovery(nil)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if err := RunInit(); err != nil {
|
if err := RunInit(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -263,6 +270,12 @@ func RunInit() error {
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}},
|
}},
|
||||||
config.CfgFuncData{"load modules", loadModules},
|
config.CfgFuncData{"load modules", loadModules},
|
||||||
|
config.CfgFuncData{"recovery console", func(cfg *config.CloudConfig) (*config.CloudConfig, error) {
|
||||||
|
if cfg.Rancher.Recovery {
|
||||||
|
recovery(nil)
|
||||||
|
}
|
||||||
|
return cfg, nil
|
||||||
|
}},
|
||||||
config.CfgFuncData{"b2d env", func(cfg *config.CloudConfig) (*config.CloudConfig, error) {
|
config.CfgFuncData{"b2d env", func(cfg *config.CloudConfig) (*config.CloudConfig, error) {
|
||||||
if dev := util.ResolveDevice("LABEL=B2D_STATE"); dev != "" {
|
if dev := util.ResolveDevice("LABEL=B2D_STATE"); dev != "" {
|
||||||
boot2DockerEnvironment = true
|
boot2DockerEnvironment = true
|
||||||
@@ -411,7 +424,7 @@ func RunInit() error {
|
|||||||
|
|
||||||
cfg, err := config.ChainCfgFuncs(nil, initFuncs)
|
cfg, err := config.ChainCfgFuncs(nil, initFuncs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
recovery(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
launchConfig, args := getLaunchConfig(cfg, &cfg.Rancher.SystemDocker)
|
launchConfig, args := getLaunchConfig(cfg, &cfg.Rancher.SystemDocker)
|
||||||
@@ -422,6 +435,7 @@ func RunInit() error {
|
|||||||
_, err = dfs.LaunchDocker(launchConfig, config.SystemDockerBin, args...)
|
_, err = dfs.LaunchDocker(launchConfig, config.SystemDockerBin, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error Launching System Docker: %s", err)
|
log.Errorf("Error Launching System Docker: %s", err)
|
||||||
|
recovery(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Code never gets here - rancher.system_docker.exec=true
|
// Code never gets here - rancher.system_docker.exec=true
|
||||||
|
96
init/recovery.go
Normal file
96
init/recovery.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package init
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
composeConfig "github.com/docker/libcompose/config"
|
||||||
|
"github.com/docker/libcompose/yaml"
|
||||||
|
"github.com/rancher/os/compose"
|
||||||
|
"github.com/rancher/os/config"
|
||||||
|
"github.com/rancher/os/netconf"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
|
||||||
|
// TODO: move this into the os-config file so it can be customised.
|
||||||
|
recoveryDockerService = composeConfig.ServiceConfigV1{
|
||||||
|
Image: config.OsBase,
|
||||||
|
Command: yaml.Command{
|
||||||
|
"ros",
|
||||||
|
"recovery-init",
|
||||||
|
},
|
||||||
|
Labels: map[string]string{
|
||||||
|
config.DetachLabel: "false",
|
||||||
|
config.ScopeLabel: "system",
|
||||||
|
},
|
||||||
|
LogDriver: "json-file",
|
||||||
|
Net: "host",
|
||||||
|
Uts: "host",
|
||||||
|
Pid: "host",
|
||||||
|
Ipc: "host",
|
||||||
|
Privileged: true,
|
||||||
|
Volumes: []string{
|
||||||
|
"/dev:/host/dev",
|
||||||
|
"/etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt.rancher",
|
||||||
|
"/lib/modules:/lib/modules",
|
||||||
|
"/lib/firmware:/lib/firmware",
|
||||||
|
"/usr/bin/ros:/usr/bin/ros:ro",
|
||||||
|
"/usr/bin/ros:/usr/bin/cloud-init-save",
|
||||||
|
"/usr/bin/ros:/usr/bin/respawn:ro",
|
||||||
|
"/usr/share/ros:/usr/share/ros:ro",
|
||||||
|
"/var/lib/rancher:/var/lib/rancher",
|
||||||
|
"/var/lib/rancher/conf:/var/lib/rancher/conf",
|
||||||
|
"/var/run:/var/run",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func recoveryServices(cfg *config.CloudConfig) (*config.CloudConfig, error) {
|
||||||
|
_, err := compose.RunServiceSet("recovery", cfg, map[string]*composeConfig.ServiceConfigV1{
|
||||||
|
"recovery": &recoveryDockerService,
|
||||||
|
})
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func recovery(initFailure error) {
|
||||||
|
if initFailure != nil {
|
||||||
|
log.Errorf("RancherOS has failed to boot: %v", initFailure)
|
||||||
|
}
|
||||||
|
log.Info("Launching recovery console")
|
||||||
|
|
||||||
|
var recoveryConfig config.CloudConfig
|
||||||
|
recoveryConfig.Rancher.Defaults = config.Defaults{
|
||||||
|
Network: netconf.NetworkConfig{
|
||||||
|
DNS: netconf.DNSConfig{
|
||||||
|
Nameservers: []string{
|
||||||
|
"8.8.8.8",
|
||||||
|
"8.8.4.4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
recoveryConfig.Rancher.BootstrapDocker = config.DockerConfig{
|
||||||
|
EngineOpts: config.EngineOpts{
|
||||||
|
Bridge: "none",
|
||||||
|
StorageDriver: "overlay",
|
||||||
|
Restart: &[]bool{false}[0],
|
||||||
|
Graph: "/var/lib/recovery-docker",
|
||||||
|
Group: "root",
|
||||||
|
Host: []string{"unix:///var/run/system-docker.sock"},
|
||||||
|
UserlandProxy: &[]bool{false}[0],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := startDocker(&recoveryConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = config.ChainCfgFuncs(&recoveryConfig,
|
||||||
|
[]config.CfgFuncData{
|
||||||
|
config.CfgFuncData{"loadImages", loadImages},
|
||||||
|
config.CfgFuncData{"recovery console", recoveryServices},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
2
main.go
2
main.go
@@ -23,6 +23,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var entrypoints = map[string]func(){
|
var entrypoints = map[string]func(){
|
||||||
|
"autologin": control.AutologinMain,
|
||||||
"cloud-init-execute": cloudinitexecute.Main,
|
"cloud-init-execute": cloudinitexecute.Main,
|
||||||
"cloud-init-save": cloudinitsave.Main,
|
"cloud-init-save": cloudinitsave.Main,
|
||||||
"console": control.ConsoleInitMain,
|
"console": control.ConsoleInitMain,
|
||||||
@@ -31,6 +32,7 @@ var entrypoints = map[string]func(){
|
|||||||
"dockerlaunch": dfs.Main,
|
"dockerlaunch": dfs.Main,
|
||||||
"init": osInit.MainInit,
|
"init": osInit.MainInit,
|
||||||
"netconf": network.Main,
|
"netconf": network.Main,
|
||||||
|
"recovery": control.AutologinMain,
|
||||||
"ros-sysinit": sysinit.Main,
|
"ros-sysinit": sysinit.Main,
|
||||||
"system-docker": systemdocker.Main,
|
"system-docker": systemdocker.Main,
|
||||||
"wait-for-docker": wait.Main,
|
"wait-for-docker": wait.Main,
|
||||||
|
@@ -14,6 +14,8 @@ rancher:
|
|||||||
network:
|
network:
|
||||||
dns:
|
dns:
|
||||||
nameservers: [8.8.8.8, 8.8.4.4]
|
nameservers: [8.8.8.8, 8.8.4.4]
|
||||||
|
ssh:
|
||||||
|
daemon: true
|
||||||
bootstrap:
|
bootstrap:
|
||||||
bootstrap:
|
bootstrap:
|
||||||
image: {{.OS_REPO}}/os-bootstrap:{{.VERSION}}{{.SUFFIX}}
|
image: {{.OS_REPO}}/os-bootstrap:{{.VERSION}}{{.SUFFIX}}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
# Add `UI vesamenu.c32` to a new line in `global.cfg` to switch to GUI bootmenu (use `sudo ros config syslinux`)
|
# Add `UI vesamenu.c32` to a new line in `global.cfg` to switch to GUI bootmenu (use `sudo ros config syslinux`)
|
||||||
UI menu.c32
|
UI menu.c32
|
||||||
TIMEOUT 20 #2s
|
TIMEOUT 30 #3s
|
||||||
PROMPT 0
|
PROMPT 0
|
||||||
|
|
||||||
# doesn't appear to work here?
|
# doesn't appear to work here?
|
||||||
|
@@ -9,23 +9,30 @@ LABEL rancheros-${LABEL}
|
|||||||
|
|
||||||
LABEL rancheros-${LABEL}-autologin
|
LABEL rancheros-${LABEL}-autologin
|
||||||
SAY rancheros-${LABEL}-autologin: autologin RancherOS ${VERSION} ${KERNEL_VERSION}
|
SAY rancheros-${LABEL}-autologin: autologin RancherOS ${VERSION} ${KERNEL_VERSION}
|
||||||
MENU LABEL rancher.autologin
|
MENU LABEL Autologin on tty1 and ttyS0
|
||||||
MENU INDENT 2
|
MENU INDENT 2
|
||||||
COM32 cmd.c32
|
COM32 cmd.c32
|
||||||
APPEND rancheros-${LABEL} rancher.autologin=tty1 rancher.autologin=ttyS0
|
APPEND rancheros-${LABEL} rancher.autologin=tty1 rancher.autologin=ttyS0
|
||||||
|
|
||||||
LABEL rancheros-${LABEL}-debug
|
LABEL rancheros-${LABEL}-debug
|
||||||
SAY rancheros-${LABEL}-debug: debug RancherOS ${VERSION} ${KERNEL_VERSION}
|
SAY rancheros-${LABEL}-debug: debug RancherOS ${VERSION} ${KERNEL_VERSION}
|
||||||
MENU LABEL rancher.debug=true
|
MENU LABEL Debug logging
|
||||||
MENU INDENT 2
|
MENU INDENT 2
|
||||||
COM32 cmd.c32
|
COM32 cmd.c32
|
||||||
APPEND rancheros-${LABEL} rancher.debug=true
|
APPEND rancheros-${LABEL} rancher.debug=true
|
||||||
|
|
||||||
LABEL rancheros-${LABEL}-debug-autologin
|
LABEL rancheros-${LABEL}-debug-autologin
|
||||||
SAY rancheros-${LABEL}-debug-autolgin: debug and autologin RancherOS ${VERSION} ${KERNEL_VERSION}
|
SAY rancheros-${LABEL}-debug-autolgin: debug and autologin RancherOS ${VERSION} ${KERNEL_VERSION}
|
||||||
MENU LABEL rancher.debug and rancher.autologin
|
MENU LABEL Autologin on tty1 and ttyS0 plus Debug logging
|
||||||
MENU INDENT 2
|
MENU INDENT 2
|
||||||
COM32 cmd.c32
|
COM32 cmd.c32
|
||||||
APPEND rancheros-${LABEL} rancher.autologin=tty1 rancher.autologin=ttyS0 rancher.debug=true
|
APPEND rancheros-${LABEL} rancher.autologin=tty1 rancher.autologin=ttyS0 rancher.debug=true
|
||||||
|
|
||||||
|
LABEL rancheros-${LABEL}-recovery
|
||||||
|
SAY rancheros-${LABEL}-recovery: recovery console RancherOS ${VERSION} ${KERNEL_VERSION}
|
||||||
|
MENU LABEL Recovery console
|
||||||
|
MENU INDENT 2
|
||||||
|
COM32 cmd.c32
|
||||||
|
APPEND rancheros-${LABEL} rancher.recovery=true
|
||||||
|
|
||||||
MENU SEPARATOR
|
MENU SEPARATOR
|
||||||
|
@@ -171,7 +171,7 @@ if [ "$APPEND_INIT" != "" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$BOOT_PXE" == "1" ]; then
|
if [ "$BOOT_PXE" == "1" ]; then
|
||||||
KERNEL_ARGS="console=tty1 rancher.console=tty1 rancher.autologin=tty1 ${KERNEL_ARGS}"
|
KERNEL_ARGS="console=tty1 rancher.autologin=tty1 ${KERNEL_ARGS}"
|
||||||
set -ex
|
set -ex
|
||||||
PIXIECORE=$(which pixiecore)
|
PIXIECORE=$(which pixiecore)
|
||||||
sudo -E $PIXIECORE boot \
|
sudo -E $PIXIECORE boot \
|
||||||
@@ -311,6 +311,7 @@ if [ "$QEMU" == "1" ]; then
|
|||||||
$(eval "${hd["$ARCH"]} ${HD}") \
|
$(eval "${hd["$ARCH"]} ${HD}") \
|
||||||
${SECOND_DRIVE_ENABLE} \
|
${SECOND_DRIVE_ENABLE} \
|
||||||
-smp 1 \
|
-smp 1 \
|
||||||
|
-device virtio-rng-pci \
|
||||||
${CLOUD_CONFIG_DISK} \
|
${CLOUD_CONFIG_DISK} \
|
||||||
-fsdev local,security_model=none,id=fsdev1,path=${HOME} \
|
-fsdev local,security_model=none,id=fsdev1,path=${HOME} \
|
||||||
-device virtio-9p-pci,id=fs1,fsdev=fsdev1,mount_tag=home \
|
-device virtio-9p-pci,id=fs1,fsdev=fsdev1,mount_tag=home \
|
||||||
@@ -338,6 +339,7 @@ elif [ "$BOOT_ISO" == "1" ] ||
|
|||||||
$(eval "${hd["$ARCH"]} ${HD}") \
|
$(eval "${hd["$ARCH"]} ${HD}") \
|
||||||
${SECOND_DRIVE_ENABLE} \
|
${SECOND_DRIVE_ENABLE} \
|
||||||
-smp 1 \
|
-smp 1 \
|
||||||
|
-device virtio-rng-pci \
|
||||||
${ISO_OPTS} \
|
${ISO_OPTS} \
|
||||||
"${@}"
|
"${@}"
|
||||||
elif [ "$QIND" == "1" ]; then
|
elif [ "$QIND" == "1" ]; then
|
||||||
|
@@ -52,4 +52,4 @@ if [ "$ENGINE_REGISTRY_MIRROR" != "" ]; then
|
|||||||
REGISTRY_MIRROR="rancher.bootstrap_docker.registry_mirror=${ENGINE_REGISTRY_MIRROR} rancher.system_docker.registry_mirror=${ENGINE_REGISTRY_MIRROR} rancher.docker.registry_mirror=${ENGINE_REGISTRY_MIRROR}"
|
REGISTRY_MIRROR="rancher.bootstrap_docker.registry_mirror=${ENGINE_REGISTRY_MIRROR} rancher.system_docker.registry_mirror=${ENGINE_REGISTRY_MIRROR} rancher.docker.registry_mirror=${ENGINE_REGISTRY_MIRROR}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
DEFAULT_KERNEL_ARGS="printk.devkmsg=on rancher.debug=true rancher.password=rancher console=${TTYCONS} rancher.autologin=${TTYCONS} ${REGISTRY_MIRROR} "
|
DEFAULT_KERNEL_ARGS="printk.devkmsg=on rancher.debug=true rancher.password=rancher console=tty1 rancher.autologin=tty1 console=${TTYCONS} rancher.autologin=${TTYCONS} ${REGISTRY_MIRROR} "
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
"no_sharedroot": {"type": "boolean"},
|
"no_sharedroot": {"type": "boolean"},
|
||||||
"log": {"type": "boolean"},
|
"log": {"type": "boolean"},
|
||||||
"force_console_rebuild": {"type": "boolean"},
|
"force_console_rebuild": {"type": "boolean"},
|
||||||
|
"recovery": {"type": "boolean"},
|
||||||
"disable": {"$ref": "#/definitions/list_of_strings"},
|
"disable": {"$ref": "#/definitions/list_of_strings"},
|
||||||
"services_include": {"type": "object"},
|
"services_include": {"type": "object"},
|
||||||
"modules": {"$ref": "#/definitions/list_of_strings"},
|
"modules": {"$ref": "#/definitions/list_of_strings"},
|
||||||
@@ -142,7 +143,8 @@
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"keys": {"type": "object"}
|
"keys": {"type": "object"},
|
||||||
|
"daemon": {"type": "boolean"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user