1
0
mirror of https://github.com/rancher/os.git synced 2025-06-23 13:37:03 +00:00
os/init/init.go

246 lines
5.5 KiB
Go
Raw Normal View History

// +build linux
2015-02-09 04:38:37 +00:00
package init
import (
2015-07-29 07:51:49 +00:00
"bufio"
2015-02-09 04:38:37 +00:00
"fmt"
"os"
"os/exec"
"strings"
"syscall"
2015-02-09 04:38:37 +00:00
log "github.com/Sirupsen/logrus"
2015-07-29 07:51:49 +00:00
"github.com/rancher/docker-from-scratch"
"github.com/rancher/os/config"
"github.com/rancher/os/util"
2015-02-09 04:38:37 +00:00
)
const (
2015-07-29 07:51:49 +00:00
STATE string = "/state"
TMPFS_MAGIC int64 = 0x01021994
RAMFS_MAGIC int64 = 0x858458f6
2015-02-09 04:38:37 +00:00
)
var (
2015-07-29 07:51:49 +00:00
mountConfig = dockerlaunch.Config{
CgroupHierarchy: map[string]string{
"cpu": "cpu",
"cpuacct": "cpu",
"net_cls": "net_cls",
"net_prio": "net_cls",
},
}
2015-02-09 04:38:37 +00:00
)
func loadModules(cfg *config.CloudConfig) (*config.CloudConfig, error) {
2015-07-29 07:51:49 +00:00
mounted := map[string]bool{}
2015-02-09 04:38:37 +00:00
2015-07-29 07:51:49 +00:00
f, err := os.Open("/proc/modules")
2015-02-09 04:38:37 +00:00
if err != nil {
return cfg, err
2015-02-09 04:38:37 +00:00
}
defer f.Close()
2015-07-29 07:51:49 +00:00
reader := bufio.NewScanner(f)
for reader.Scan() {
mounted[strings.SplitN(reader.Text(), " ", 2)[0]] = true
}
2015-08-04 21:45:38 +00:00
for _, module := range cfg.Rancher.Modules {
2015-07-29 07:51:49 +00:00
if mounted[module] {
continue
}
2015-02-09 04:38:37 +00:00
log.Debugf("Loading module %s", module)
2015-07-29 07:51:49 +00:00
if err := exec.Command("modprobe", module).Run(); err != nil {
log.Errorf("Could not load module %s, err %v", module, err)
2015-02-09 04:38:37 +00:00
}
}
return cfg, nil
2015-02-09 04:38:37 +00:00
}
func sysInit(c *config.CloudConfig) (*config.CloudConfig, error) {
2015-07-29 07:51:49 +00:00
args := append([]string{config.SYSINIT_BIN}, os.Args[1:]...)
cmd := &exec.Cmd{
Path: config.ROS_BIN,
Args: args,
}
2015-07-29 07:51:49 +00:00
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
2015-02-09 04:38:37 +00:00
if err := cmd.Start(); err != nil {
return c, err
2015-02-09 04:38:37 +00:00
}
return c, os.Stdin.Close()
2015-02-09 04:38:37 +00:00
}
func MainInit() {
if err := RunInit(); err != nil {
log.Fatal(err)
}
}
func mountConfigured(display, dev, fsType, target string) error {
2015-02-09 04:38:37 +00:00
var err error
2015-02-12 22:34:16 +00:00
if dev == "" {
2015-07-29 07:51:49 +00:00
return nil
}
2015-02-12 22:34:16 +00:00
dev = util.ResolveDevice(dev)
2015-07-29 07:51:49 +00:00
if dev == "" {
return fmt.Errorf("Could not resolve device %q", dev)
2015-07-29 07:51:49 +00:00
}
if fsType == "auto" {
fsType, err = util.GetFsType(dev)
}
2015-02-12 22:34:16 +00:00
2015-07-29 07:51:49 +00:00
if err != nil {
return err
2015-02-09 04:38:37 +00:00
}
2015-07-29 07:51:49 +00:00
log.Debugf("FsType has been set to %s", fsType)
log.Infof("Mounting %s device %s to %s", display, dev, target)
return util.Mount(dev, target, fsType, "")
}
func mountState(cfg *config.CloudConfig) error {
return mountConfigured("state", cfg.Rancher.State.Dev, cfg.Rancher.State.FsType, STATE)
}
2015-02-09 04:38:37 +00:00
func mountOem(cfg *config.CloudConfig) (*config.CloudConfig, error) {
if cfg == nil {
var err error
if cfg, err = config.LoadConfig(); err != nil {
return cfg, err
}
}
if err := mountConfigured("oem", cfg.Rancher.State.OemDev, cfg.Rancher.State.OemFsType, config.OEM); err != nil {
2016-02-04 15:44:08 +00:00
log.Debugf("Not mounting OEM: %v", err)
} else {
log.Infof("Mounted OEM: %s", cfg.Rancher.State.OemDev)
}
return cfg, nil
}
2015-08-04 21:45:38 +00:00
func tryMountState(cfg *config.CloudConfig) error {
2015-07-29 07:51:49 +00:00
if mountState(cfg) == nil {
return nil
}
// If we failed to mount lets run bootstrap and try again
if err := bootstrap(cfg); err != nil {
return err
2015-02-17 08:18:48 +00:00
}
2015-02-09 04:38:37 +00:00
2015-07-29 07:51:49 +00:00
return mountState(cfg)
2015-04-03 21:59:24 +00:00
}
func tryMountAndBootstrap(cfg *config.CloudConfig) (*config.CloudConfig, error) {
if isInitrd() {
if err := tryMountState(cfg); !cfg.Rancher.State.Required && err != nil {
return cfg, nil
} else if err != nil {
return cfg, err
}
2015-04-03 21:59:24 +00:00
log.Debugf("Switching to new root at %s %s", STATE, cfg.Rancher.State.Directory)
if err := switchRoot(STATE, cfg.Rancher.State.Directory, cfg.Rancher.RmUsr); err != nil {
return cfg, err
}
}
return mountOem(cfg)
2015-04-03 21:59:24 +00:00
}
2015-08-04 21:45:38 +00:00
func getLaunchConfig(cfg *config.CloudConfig, dockerCfg *config.DockerConfig) (*dockerlaunch.Config, []string) {
2015-07-29 07:51:49 +00:00
var launchConfig dockerlaunch.Config
args := dockerlaunch.ParseConfig(&launchConfig, append(dockerCfg.Args, dockerCfg.ExtraArgs...)...)
2016-04-15 17:38:31 +00:00
launchConfig.DnsConfig.Nameservers = cfg.Rancher.DefaultNetwork.Dns.Nameservers
launchConfig.DnsConfig.Search = cfg.Rancher.DefaultNetwork.Dns.Search
launchConfig.Environment = dockerCfg.Environment
2015-09-19 05:27:53 +00:00
launchConfig.EmulateSystemd = true
2015-07-29 07:51:49 +00:00
2015-08-04 21:45:38 +00:00
if !cfg.Rancher.Debug {
2015-07-29 07:51:49 +00:00
launchConfig.LogFile = config.SYSTEM_DOCKER_LOG
2015-04-03 21:59:24 +00:00
}
2015-07-29 07:51:49 +00:00
return &launchConfig, args
2015-04-03 21:59:24 +00:00
}
func isInitrd() bool {
var stat syscall.Statfs_t
syscall.Statfs("/", &stat)
return int64(stat.Type) == TMPFS_MAGIC || int64(stat.Type) == RAMFS_MAGIC
}
2015-02-09 04:38:37 +00:00
func RunInit() error {
2015-04-03 21:59:24 +00:00
os.Setenv("PATH", "/sbin:/usr/sbin:/usr/bin")
if isInitrd() {
log.Debug("Booting off an in-memory filesystem")
// Magic setting to tell Docker to do switch_root and not pivot_root
os.Setenv("DOCKER_RAMDISK", "true")
} else {
log.Debug("Booting off a persistent filesystem")
}
2015-02-09 04:38:37 +00:00
initFuncs := []config.CfgFunc{
func(c *config.CloudConfig) (*config.CloudConfig, error) {
return c, dockerlaunch.PrepareFs(&mountConfig)
2015-02-09 04:38:37 +00:00
},
mountOem,
func(_ *config.CloudConfig) (*config.CloudConfig, error) {
cfg, err := config.LoadConfig()
if err != nil {
return cfg, err
2015-02-09 04:38:37 +00:00
}
2015-02-14 16:34:11 +00:00
2015-08-04 21:45:38 +00:00
if cfg.Rancher.Debug {
cfgString, err := config.Dump(false, true)
2015-08-20 13:06:48 +00:00
if err != nil {
log.WithFields(log.Fields{"err": err}).Error("Error serializing config")
} else {
2015-07-29 07:51:49 +00:00
log.Debugf("Config: %s", cfgString)
}
2015-02-14 16:34:11 +00:00
}
return cfg, nil
2015-02-09 04:38:37 +00:00
},
loadModules,
tryMountAndBootstrap,
func(_ *config.CloudConfig) (*config.CloudConfig, error) {
return config.LoadConfig()
},
loadModules,
2016-02-20 00:11:32 +00:00
func(c *config.CloudConfig) (*config.CloudConfig, error) {
return c, dockerlaunch.PrepareFs(&mountConfig)
},
initializeSelinux,
2015-02-09 04:38:37 +00:00
sysInit,
}
cfg, err := config.ChainCfgFuncs(nil, initFuncs...)
if err != nil {
2015-02-09 04:38:37 +00:00
return err
}
launchConfig, args := getLaunchConfig(cfg, &cfg.Rancher.SystemDocker)
launchConfig.Fork = !cfg.Rancher.SystemDocker.Exec
2015-07-29 07:51:49 +00:00
log.Info("Launching System Docker")
_, err = dockerlaunch.LaunchDocker(launchConfig, config.DOCKER_BIN, args...)
if err != nil {
return err
}
2016-02-20 00:11:32 +00:00
return pidOne()
2015-02-09 04:38:37 +00:00
}