1
0
mirror of https://github.com/rancher/os.git synced 2025-05-03 13:46:20 +00:00
os/init/init.go

307 lines
6.2 KiB
Go
Raw Normal View History

2015-02-09 04:38:37 +00:00
package init
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
"strings"
"syscall"
"time"
log "github.com/Sirupsen/logrus"
"github.com/rancherio/os/config"
"github.com/rancherio/os/util"
)
const (
2015-02-14 16:33:58 +00:00
STATE string = "/var"
2015-02-09 04:38:37 +00:00
)
var (
dirs []string = []string{
"/bin",
"/dev",
"/dev/pts",
2015-02-14 16:33:58 +00:00
"/etc/ssl/certs",
2015-02-09 04:38:37 +00:00
"/proc",
"/sbin",
"/sys",
"/usr/bin",
2015-02-14 16:33:58 +00:00
"/var/run",
}
statedirs []string = []string{
2015-02-09 04:38:37 +00:00
"/var/run",
}
mounts [][]string = [][]string{
[]string{"none", "/etc/docker", "tmpfs", ""},
[]string{"none", "/proc", "proc", ""},
[]string{"devtmpfs", "/dev", "devtmpfs", ""},
[]string{"none", "/sys", "sysfs", ""},
[]string{"none", "/sys/fs/cgroup", "tmpfs", ""},
[]string{"none", "/dev/pts", "devpts", ""},
[]string{"none", "/var/run", "tmpfs", ""},
}
cgroups []string = []string{
"perf_event",
"net_cls",
"freezer",
"devices",
"blkio",
"memory",
"cpuacct",
"cpu",
"cpuset",
}
// Notice this map is the reverse order of a "ln -s x y" command
// so map[y] = x
symlinks map[string]string = map[string]string{
"/etc/ssl/certs/ca-certificates.crt": "/ca.crt",
"/bin/busybox": "/busybox",
"/sbin/init-sys": "/init",
"/sbin/init-user": "/init",
"/sbin/modprobe": "/bin/busybox",
"/usr/bin/docker": "/docker",
"/usr/bin/openvt": "/busybox",
"/usr/bin/system-docker": "/init",
}
)
func createSymlinks(cfg *config.Config) error {
for dest, src := range symlinks {
if _, err := os.Stat(dest); os.IsNotExist(err) {
log.Debugf("Symlinking %s => %s", src, dest)
if err = os.Symlink(src, dest); err != nil {
return err
}
}
}
return nil
}
func createDirs(dirs ...string) error {
for _, dir := range dirs {
if _, err := os.Stat(dir); os.IsNotExist(err) {
log.Debugf("Creating %s", dir)
err = os.MkdirAll(dir, 0755)
if err != nil {
return err
}
}
}
return nil
}
func createMounts(mounts ...[]string) error {
for _, mount := range mounts {
log.Debugf("Mounting %s %s %s %s", mount[0], mount[1], mount[2], mount[3])
err := util.Mount(mount[0], mount[1], mount[2], mount[3])
if err != nil {
return err
}
}
return nil
}
func remountRo(cfg *config.Config) error {
return util.Remount("/", "ro")
}
func mountCgroups(cfg *config.Config) error {
for _, cgroup := range cgroups {
err := createDirs("/sys/fs/cgroup/" + cgroup)
if err != nil {
return err
}
err = createMounts([][]string{
[]string{"none", "sys/fs/cgroup/" + cgroup, "cgroup", cgroup},
}...)
if err != nil {
return err
}
}
log.Debug("Done mouting cgroupfs")
return nil
}
func extractModules(cfg *config.Config) error {
if _, err := os.Stat(cfg.ModulesArchive); os.IsNotExist(err) {
log.Debug("Modules do not exist")
return nil
}
log.Debug("Extracting modules")
return util.ExtractTar(cfg.ModulesArchive, "/")
}
func setResolvConf(cfg *config.Config) error {
log.Debug("Creating /etc/resolv.conf")
//f, err := os.OpenFile("/etc/resolv.conf", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
f, err := os.Create("/etc/resolv.conf")
if err != nil {
return err
}
defer f.Close()
for _, dns := range cfg.Dns {
content := fmt.Sprintf("nameserver %s\n", dns)
if _, err = f.Write([]byte(content)); err != nil {
return err
}
}
return nil
}
func loadModules(cfg *config.Config) error {
filesystems, err := ioutil.ReadFile("/proc/filesystems")
if err != nil {
return err
}
if !strings.Contains(string(filesystems), "nodev\toverlay\n") {
log.Debug("Loading overlay module")
err = exec.Command("/sbin/modprobe", "overlay").Run()
if err != nil {
return err
}
}
for _, module := range cfg.Modules {
log.Debugf("Loading module %s", module)
err = exec.Command("/sbin/modprobe", module).Run()
if err != nil {
return err
}
}
return nil
}
func sysInit(cfg *config.Config) error {
args := append([]string{"/sbin/init-sys"}, os.Args[1:]...)
var cmd *exec.Cmd
if util.IsRunningInTty() {
cmd = exec.Command(args[0], args[1:]...)
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
} else {
args = append([]string{"openvt", "-s"}, args...)
cmd = exec.Command(args[0], args[1:]...)
}
2015-02-09 04:38:37 +00:00
if err := cmd.Start(); err != nil {
return err
}
return os.Stdin.Close()
2015-02-09 04:38:37 +00:00
}
func execDocker(cfg *config.Config) error {
log.Info("Launching Docker")
os.Stdin.Close()
2015-02-09 04:38:37 +00:00
return syscall.Exec(cfg.DockerBin, cfg.SystemDockerArgs, os.Environ())
}
func MainInit() {
if err := RunInit(); err != nil {
log.Fatal(err)
}
}
func mountState(cfg *config.Config) error {
var err error
if len(cfg.StateDev) == 0 {
log.Debugf("State will not be persisted")
err = util.Mount("none", STATE, "tmpfs", "")
} else {
log.Debugf("Mounting state device %s", cfg.StateDev)
err = util.Mount(cfg.StateDev, STATE, cfg.StateDevFSType, "")
}
if err != nil {
return err
}
for _, i := range []string{"docker", "images"} {
dir := path.Join(STATE, i)
err = os.MkdirAll(dir, 0755)
if err != nil {
return err
}
}
//log.Debugf("Bind mounting %s to %s", path.Join(STATE, "docker"), DOCKER)
//err = util.Mount(path.Join(STATE, "docker"), DOCKER, "", "bind")
//if err != nil && cfg.StateRequired {
// return err
//}
2015-02-09 04:38:37 +00:00
return nil
}
func pause(cfg *config.Config) error {
time.Sleep(5 + time.Minute)
return nil
}
func RunInit() error {
var cfg config.Config
os.Setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
os.Setenv("DOCKER_RAMDISK", "true")
initFuncs := []config.InitFunc{
func(cfg *config.Config) error {
return createDirs(dirs...)
},
func(cfg *config.Config) error {
return createMounts(mounts...)
},
func(cfg *config.Config) error {
newCfg, err := config.LoadConfig()
2015-02-14 16:34:11 +00:00
if err == nil {
if newCfg.Debug {
newCfg, err = config.LoadConfig()
}
}
2015-02-09 04:38:37 +00:00
if err == nil {
*cfg = *newCfg
}
2015-02-14 16:34:11 +00:00
if cfg.Debug {
log.Debugf("Config: %s", cfg.Dump())
}
2015-02-09 04:38:37 +00:00
return err
},
createSymlinks,
setResolvConf,
extractModules,
remountRo,
mountCgroups,
loadModules,
mountState,
2015-02-14 16:33:58 +00:00
func(cfg *config.Config) error {
return createDirs(statedirs...)
},
2015-02-09 04:38:37 +00:00
sysInit,
}
if err := config.RunInitFuncs(&cfg, initFuncs); err != nil {
return err
}
return execDocker(&cfg)
}