1
0
mirror of https://github.com/rancher/os.git synced 2025-08-31 14:23:11 +00:00

Merge pull request #1931 from SvenDowideit/autologin-and-recovery-console

WIP Autologin and recovery console
This commit is contained in:
Sven Dowideit
2017-07-17 15:28:11 +10:00
committed by GitHub
25 changed files with 436 additions and 67 deletions

103
cmd/control/autologin.go Normal file
View 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
}

View File

@@ -101,6 +101,13 @@ func Main() {
SkipFlagParsing: true,
Action: preloadImagesAction,
},
{
Name: "recovery-init",
Hidden: true,
HideHelp: true,
SkipFlagParsing: true,
Action: recoveryInitAction,
},
{
Name: "switch-console",
Hidden: true,

View File

@@ -225,7 +225,15 @@ func merge(c *cli.Context) error {
}
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
@@ -255,7 +263,7 @@ func validate(c *cli.Context) error {
if err != nil {
log.Fatal(err)
}
validationErrors, err := config.Validate(bytes)
validationErrors, err := config.ValidateBytes(bytes)
if err != nil {
log.Fatal(err)
}

View File

@@ -2,18 +2,19 @@ package control
import (
"fmt"
"io/ioutil"
"sort"
"strings"
"golang.org/x/net/context"
"github.com/codegangsta/cli"
"github.com/docker/docker/reference"
composeConfig "github.com/docker/libcompose/config"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/cmd/control/service"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/docker"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
"github.com/rancher/os/util/network"
@@ -57,7 +58,7 @@ func consoleSwitch(c *cli.Context) error {
cfg := config.LoadConfig()
validateConsole(newConsole, cfg)
if newConsole == currentConsole() {
if newConsole == CurrentConsole() {
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 {
cfg := config.LoadConfig()
consoles := availableConsoles(cfg)
currentConsole := currentConsole()
CurrentConsole := CurrentConsole()
for _, console := range consoles {
if console == currentConsole {
if console == CurrentConsole {
fmt.Printf("current %s\n", console)
} else if console == cfg.Rancher.Console {
fmt.Printf("enabled %s\n", console)
@@ -159,12 +160,32 @@ func availableConsoles(cfg *config.CloudConfig) []string {
return consoles
}
func currentConsole() (console string) {
consoleBytes, err := ioutil.ReadFile("/run/console-done")
if err == nil {
console = strings.TrimSpace(string(consoleBytes))
} else {
// CurrentConsole gets the name of the console that's running
func CurrentConsole() (console string) {
// TODO: replace this docker container look up with a libcompose service lookup?
// sudo system-docker inspect --format "{{.Config.Image}}" console
client, err := docker.NewSystemClient()
if err != nil {
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
}

View File

@@ -11,7 +11,6 @@ import (
"strings"
"syscall"
"github.com/SvenDowideit/cpuid"
"github.com/codegangsta/cli"
"github.com/rancher/os/cmd/cloudinitexecute"
"github.com/rancher/os/config"
@@ -82,7 +81,7 @@ func consoleInitFunc() error {
log.Error(err)
}
if err := writeRespawn(); err != nil {
if err := writeRespawn("rancher", cfg.Rancher.SSH.Daemon, false); err != nil {
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..)
if err := ioutil.WriteFile("/etc/issue", []byte(`
, , ______ _ _____ _____TM
,------------|'------'| | ___ \\ | | / _ / ___|
/ . '-' |- | |_/ /__ _ _ __ ___| |__ ___ _ __ | | | \\ '--.
\\/| | | | // _' | '_ \\ / __| '_ \\ / _ \\ '__' | | | |'--. \\
| .________.'----' | |\\ \\ (_| | | | | (__| | | | __/ | | \\_/ /\\__/ /
| | | | \\_| \\_\\__,_|_| |_|\\___|_| |_|\\___|_| \\___/\\____/
\\___/ \\___/ \s \r
RancherOS `+config.Version+` \n \l `+cpuid.CPU.HypervisorName+`
`), 0644); err != nil {
if err := ioutil.WriteFile("/etc/issue", []byte(config.Banner), 0644); err != nil {
log.Error(err)
}
@@ -137,7 +126,7 @@ func consoleInitFunc() error {
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)
}
@@ -155,15 +144,20 @@ func consoleInitFunc() error {
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
autologinBin := "/usr/bin/autologin"
if recovery {
autologinBin = "/usr/bin/recovery"
}
for i := 1; i < 7; i++ {
tty := fmt.Sprintf("tty%d", i)
respawnConf.WriteString(gettyCmd)
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))
}
@@ -175,23 +169,25 @@ func generateRespawnConf(cmdline string) string {
respawnConf.WriteString(gettyCmd)
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("/usr/sbin/sshd -D")
if sshd {
respawnConf.WriteString("/usr/sbin/sshd -D")
}
return respawnConf.String()
}
func writeRespawn() error {
func writeRespawn(user string, sshd, recovery bool) error {
cmdline, err := ioutil.ReadFile("/proc/cmdline")
if err != nil {
return err
}
respawn := generateRespawnConf(string(cmdline))
respawn := generateRespawnConf(string(cmdline), user, sshd, recovery)
files, err := ioutil.ReadDir("/etc/respawn.conf.d")
if err == nil {

View File

@@ -10,7 +10,6 @@ import (
"time"
"github.com/codegangsta/cli"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)
@@ -22,6 +21,7 @@ const (
)
func dockerInitAction(c *cli.Context) error {
// TODO: this should be replaced by a "Console ready event watcher"
for {
if _, err := os.Stat(consoleDone); err == nil {
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),
}
cfg := config.LoadConfig()
if err := ioutil.WriteFile(dockerDone, []byte(cfg.Rancher.Docker.Engine), 0644); err != nil {
// TODO: this should be replaced by a "Docker ready event watcher"
if err := ioutil.WriteFile(dockerDone, []byte(CurrentEngine()), 0644); err != nil {
log.Error(err)
}

View File

@@ -2,17 +2,18 @@ package control
import (
"fmt"
"io/ioutil"
"sort"
"strings"
"golang.org/x/net/context"
"github.com/codegangsta/cli"
"github.com/docker/docker/reference"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/cmd/control/service"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/docker"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
"github.com/rancher/os/util/network"
@@ -104,7 +105,7 @@ func engineEnable(c *cli.Context) error {
func engineList(c *cli.Context) error {
cfg := config.LoadConfig()
engines := availableEngines(cfg)
currentEngine := currentEngine()
currentEngine := CurrentEngine()
for _, engine := range engines {
if engine == currentEngine {
@@ -135,12 +136,33 @@ func availableEngines(cfg *config.CloudConfig) []string {
return engines
}
func currentEngine() (engine string) {
engineBytes, err := ioutil.ReadFile(dockerDone)
if err == nil {
engine = strings.TrimSpace(string(engineBytes))
} else {
log.Warnf("Failed to detect current Docker engine: %v", err)
// CurrentEngine gets the name of the docker that's running
func CurrentEngine() (engine string) {
// sudo system-docker inspect --format "{{.Config.Image}}" docker
client, err := docker.NewSystemClient()
if err != nil {
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
}

View File

@@ -79,6 +79,8 @@ func writeFiles(cfg *config.CloudConfig) error {
func setupCommandSymlinks() {
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-save"},
{config.RosBin, "/usr/bin/dockerlaunch"},

View 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())
}

View File

@@ -1,10 +1,25 @@
package config
import (
"io/ioutil"
"strings"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/rancher/os/util"
)
const Banner = `
, , ______ _ _____ _____TM
,------------|'------'| | ___ \\ | | / _ / ___|
/ . '-' |- | |_/ /__ _ _ __ ___| |__ ___ _ __ | | | \\ '--.
\\/| | | | // _' | '_ \\ / __| '_ \\ / _ \\ '__' | | | |'--. \\
| .________.'----' | |\\ \\ (_| | | | | (__| | | | __/ | | \\_/ /\\__/ /
| | | | \\_| \\_\\__,_|_| |_|\\___|_| |_|\\___|_| \\___/\\____/
\\___/ \\___/ \s \r
RancherOS \v \n \l
`
func Merge(bytes []byte) error {
data, err := readConfigs(bytes, false, true)
if err != nil {
@@ -60,3 +75,12 @@ func Set(key string, value interface{}) error {
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]
}

View File

@@ -71,8 +71,19 @@ func LoadConfigWithPrefix(dirPrefix string) *CloudConfig {
cfg := &CloudConfig{}
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)
// 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{}
}
cfg = amendNils(cfg)

View File

@@ -37,6 +37,7 @@ var schema = `{
"no_sharedroot": {"type": "boolean"},
"log": {"type": "boolean"},
"force_console_rebuild": {"type": "boolean"},
"recovery": {"type": "boolean"},
"disable": {"$ref": "#/definitions/list_of_strings"},
"services_include": {"type": "object"},
"modules": {"$ref": "#/definitions/list_of_strings"},
@@ -144,7 +145,8 @@ var schema = `{
"additionalProperties": false,
"properties": {
"keys": {"type": "object"}
"keys": {"type": "object"},
"daemon": {"type": "boolean"}
}
},

View File

@@ -113,6 +113,7 @@ type RancherConfig struct {
NoSharedRoot bool `yaml:"no_sharedroot,omitempty"`
Log bool `yaml:"log,omitempty"`
ForceConsoleRebuild bool `yaml:"force_console_rebuild,omitempty"`
Recovery bool `yaml:"recovery,omitempty"`
Disable []string `yaml:"disable,omitempty"`
ServicesInclude map[string]bool `yaml:"services_include,omitempty"`
Modules []string `yaml:"modules,omitempty"`
@@ -174,7 +175,8 @@ type DockerConfig 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 {

View File

@@ -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{}
if err := yaml.Unmarshal([]byte(bytes), &rawCfg); err != nil {
return nil, err
}
return ValidateRawCfg(rawCfg)
}
func ValidateRawCfg(rawCfg interface{}) (*gojsonschema.Result, error) {
rawCfg = ConvertKeysToStrings(rawCfg).(map[string]interface{})
loader := gojsonschema.NewGoLoader(rawCfg)
schemaLoader := gojsonschema.NewStringLoader(schema)

View File

@@ -2,7 +2,6 @@ package docker
import (
"fmt"
"io/ioutil"
"strings"
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
}
b, err := ioutil.ReadFile("/proc/version")
if err == nil {
elem := strings.Split(string(b), " ")
environment["KERNEL_VERSION"] = elem[2]
log.Debugf("Using /proc/version to set rancher.environment.KERNEL_VERSION = %s", elem[2])
if v := config.GetKernelVersion(); v != "" {
environment["KERNEL_VERSION"] = v
log.Debugf("Using /proc/version to set rancher.environment.KERNEL_VERSION = %s", v)
}
return environment
}

View File

@@ -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
@@ -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.
#### 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
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
$ 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.

View File

@@ -94,6 +94,13 @@ func sysInit(c *config.CloudConfig) (*config.CloudConfig, error) {
func MainInit() {
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 {
log.Fatal(err)
@@ -263,6 +270,12 @@ func RunInit() error {
return cfg, nil
}},
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) {
if dev := util.ResolveDevice("LABEL=B2D_STATE"); dev != "" {
boot2DockerEnvironment = true
@@ -411,7 +424,7 @@ func RunInit() error {
cfg, err := config.ChainCfgFuncs(nil, initFuncs)
if err != nil {
return err
recovery(err)
}
launchConfig, args := getLaunchConfig(cfg, &cfg.Rancher.SystemDocker)
@@ -422,6 +435,7 @@ func RunInit() error {
_, err = dfs.LaunchDocker(launchConfig, config.SystemDockerBin, args...)
if err != nil {
log.Errorf("Error Launching System Docker: %s", err)
recovery(err)
return err
}
// Code never gets here - rancher.system_docker.exec=true

96
init/recovery.go Normal file
View 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)
}
}

View File

@@ -23,6 +23,7 @@ import (
)
var entrypoints = map[string]func(){
"autologin": control.AutologinMain,
"cloud-init-execute": cloudinitexecute.Main,
"cloud-init-save": cloudinitsave.Main,
"console": control.ConsoleInitMain,
@@ -31,6 +32,7 @@ var entrypoints = map[string]func(){
"dockerlaunch": dfs.Main,
"init": osInit.MainInit,
"netconf": network.Main,
"recovery": control.AutologinMain,
"ros-sysinit": sysinit.Main,
"system-docker": systemdocker.Main,
"wait-for-docker": wait.Main,

View File

@@ -14,6 +14,8 @@ rancher:
network:
dns:
nameservers: [8.8.8.8, 8.8.4.4]
ssh:
daemon: true
bootstrap:
bootstrap:
image: {{.OS_REPO}}/os-bootstrap:{{.VERSION}}{{.SUFFIX}}

View File

@@ -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`)
UI menu.c32
TIMEOUT 20 #2s
TIMEOUT 30 #3s
PROMPT 0
# doesn't appear to work here?

View File

@@ -9,23 +9,30 @@ LABEL rancheros-${LABEL}
LABEL rancheros-${LABEL}-autologin
SAY rancheros-${LABEL}-autologin: autologin RancherOS ${VERSION} ${KERNEL_VERSION}
MENU LABEL rancher.autologin
MENU LABEL Autologin on tty1 and ttyS0
MENU INDENT 2
COM32 cmd.c32
APPEND rancheros-${LABEL} rancher.autologin=tty1 rancher.autologin=ttyS0
LABEL rancheros-${LABEL}-debug
SAY rancheros-${LABEL}-debug: debug RancherOS ${VERSION} ${KERNEL_VERSION}
MENU LABEL rancher.debug=true
MENU LABEL Debug logging
MENU INDENT 2
COM32 cmd.c32
APPEND rancheros-${LABEL} rancher.debug=true
LABEL rancheros-${LABEL}-debug-autologin
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
COM32 cmd.c32
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

View File

@@ -171,7 +171,7 @@ if [ "$APPEND_INIT" != "" ]; then
fi
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
PIXIECORE=$(which pixiecore)
sudo -E $PIXIECORE boot \
@@ -311,6 +311,7 @@ if [ "$QEMU" == "1" ]; then
$(eval "${hd["$ARCH"]} ${HD}") \
${SECOND_DRIVE_ENABLE} \
-smp 1 \
-device virtio-rng-pci \
${CLOUD_CONFIG_DISK} \
-fsdev local,security_model=none,id=fsdev1,path=${HOME} \
-device virtio-9p-pci,id=fs1,fsdev=fsdev1,mount_tag=home \
@@ -338,6 +339,7 @@ elif [ "$BOOT_ISO" == "1" ] ||
$(eval "${hd["$ARCH"]} ${HD}") \
${SECOND_DRIVE_ENABLE} \
-smp 1 \
-device virtio-rng-pci \
${ISO_OPTS} \
"${@}"
elif [ "$QIND" == "1" ]; then

View File

@@ -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}"
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} "

View File

@@ -35,6 +35,7 @@
"no_sharedroot": {"type": "boolean"},
"log": {"type": "boolean"},
"force_console_rebuild": {"type": "boolean"},
"recovery": {"type": "boolean"},
"disable": {"$ref": "#/definitions/list_of_strings"},
"services_include": {"type": "object"},
"modules": {"$ref": "#/definitions/list_of_strings"},
@@ -142,7 +143,8 @@
"additionalProperties": false,
"properties": {
"keys": {"type": "object"}
"keys": {"type": "object"},
"daemon": {"type": "boolean"}
}
},