2015-02-09 04:38:37 +00:00
|
|
|
package init
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"strings"
|
|
|
|
"syscall"
|
|
|
|
|
|
|
|
log "github.com/Sirupsen/logrus"
|
2015-04-03 21:59:24 +00:00
|
|
|
"github.com/rancherio/os/cmd/network"
|
2015-02-09 04:38:37 +00:00
|
|
|
"github.com/rancherio/os/config"
|
|
|
|
"github.com/rancherio/os/util"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2015-04-16 05:57:59 +00:00
|
|
|
STATE string = "/var"
|
|
|
|
SYSTEM_DOCKER string = "/usr/bin/system-docker"
|
|
|
|
DOCKER string = "/usr/bin/docker"
|
|
|
|
SYSINIT string = "/sbin/rancher-sysinit"
|
2015-02-09 04:38:37 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
dirs []string = []string{
|
2015-02-14 16:33:58 +00:00
|
|
|
"/etc/ssl/certs",
|
2015-02-09 04:38:37 +00:00
|
|
|
"/sbin",
|
|
|
|
"/usr/bin",
|
2015-04-03 21:59:24 +00:00
|
|
|
"/usr/sbin",
|
2015-02-09 04:38:37 +00:00
|
|
|
}
|
2015-02-21 07:34:23 +00:00
|
|
|
postDirs []string = []string{
|
|
|
|
"/var/log",
|
2015-03-18 13:21:32 +00:00
|
|
|
"/var/lib/rancher/state/home",
|
|
|
|
"/var/lib/rancher/state/opt",
|
2015-02-21 07:34:23 +00:00
|
|
|
}
|
2015-02-09 04:38:37 +00:00
|
|
|
mounts [][]string = [][]string{
|
2015-02-19 18:27:23 +00:00
|
|
|
[]string{"devtmpfs", "/dev", "devtmpfs", ""},
|
|
|
|
[]string{"none", "/dev/pts", "devpts", ""},
|
2015-02-09 04:38:37 +00:00
|
|
|
[]string{"none", "/etc/docker", "tmpfs", ""},
|
|
|
|
[]string{"none", "/proc", "proc", ""},
|
2015-02-19 18:27:23 +00:00
|
|
|
[]string{"none", "/run", "tmpfs", ""},
|
2015-02-09 04:38:37 +00:00
|
|
|
[]string{"none", "/sys", "sysfs", ""},
|
|
|
|
[]string{"none", "/sys/fs/cgroup", "tmpfs", ""},
|
2015-02-19 18:27:23 +00:00
|
|
|
}
|
|
|
|
postMounts [][]string = [][]string{
|
|
|
|
[]string{"none", "/var/run", "tmpfs", ""},
|
2015-02-09 04:38:37 +00:00
|
|
|
}
|
|
|
|
cgroups []string = []string{
|
|
|
|
"blkio",
|
|
|
|
"cpu",
|
2015-02-19 18:27:23 +00:00
|
|
|
"cpuacct",
|
2015-02-09 04:38:37 +00:00
|
|
|
"cpuset",
|
2015-02-19 18:27:23 +00:00
|
|
|
"devices",
|
|
|
|
"freezer",
|
|
|
|
"memory",
|
|
|
|
"net_cls",
|
|
|
|
"perf_event",
|
2015-02-09 04:38:37 +00:00
|
|
|
}
|
|
|
|
// 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",
|
2015-02-16 23:38:49 +00:00
|
|
|
"/sbin/modprobe": "/busybox",
|
2015-04-03 21:59:24 +00:00
|
|
|
"/usr/sbin/iptables": "/xtables-multi",
|
2015-02-16 23:38:49 +00:00
|
|
|
DOCKER: "/docker",
|
2015-04-16 05:57:59 +00:00
|
|
|
SYSTEM_DOCKER: "/docker",
|
2015-02-19 18:27:23 +00:00
|
|
|
SYSINIT: "/init",
|
2015-03-18 13:21:32 +00:00
|
|
|
"/home": "/var/lib/rancher/state/home",
|
|
|
|
"/opt": "/var/lib/rancher/state/opt",
|
|
|
|
}
|
2015-02-09 04:38:37 +00:00
|
|
|
)
|
|
|
|
|
2015-03-18 13:21:32 +00:00
|
|
|
func createSymlinks(cfg *config.Config, symlinks map[string]string) error {
|
2015-02-16 23:38:49 +00:00
|
|
|
log.Debug("Creating symlinking")
|
2015-02-09 04:38:37 +00:00
|
|
|
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 {
|
2015-02-21 07:34:23 +00:00
|
|
|
log.Info("Remouting root read only")
|
2015-02-09 04:38:37 +00:00
|
|
|
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 {
|
2015-02-17 08:18:48 +00:00
|
|
|
if _, err := os.Stat(config.MODULES_ARCHIVE); os.IsNotExist(err) {
|
2015-02-09 04:38:37 +00:00
|
|
|
log.Debug("Modules do not exist")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Debug("Extracting modules")
|
2015-02-17 08:18:48 +00:00
|
|
|
return util.ExtractTar(config.MODULES_ARCHIVE, "/")
|
2015-02-09 04:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
2015-03-18 13:21:32 +00:00
|
|
|
for _, dns := range cfg.Network.Dns.Nameservers {
|
2015-02-09 04:38:37 +00:00
|
|
|
content := fmt.Sprintf("nameserver %s\n", dns)
|
|
|
|
if _, err = f.Write([]byte(content)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 13:21:32 +00:00
|
|
|
search := strings.Join(cfg.Network.Dns.Search, " ")
|
|
|
|
if search != "" {
|
|
|
|
content := fmt.Sprintf("search %s\n", search)
|
|
|
|
if _, err = f.Write([]byte(content)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg.Network.Dns.Domain != "" {
|
|
|
|
content := fmt.Sprintf("domain %s\n", cfg.Network.Dns.Domain)
|
|
|
|
if _, err = f.Write([]byte(content)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-09 04:38:37 +00:00
|
|
|
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 {
|
2015-02-19 18:27:23 +00:00
|
|
|
args := append([]string{SYSINIT}, os.Args[1:]...)
|
2015-02-14 16:35:12 +00:00
|
|
|
|
|
|
|
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 {
|
|
|
|
cmd = exec.Command(args[0], args[1:]...)
|
|
|
|
}
|
|
|
|
|
2015-02-09 04:38:37 +00:00
|
|
|
if err := cmd.Start(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-02-14 16:35:12 +00:00
|
|
|
return os.Stdin.Close()
|
2015-02-09 04:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func execDocker(cfg *config.Config) error {
|
2015-02-21 07:34:23 +00:00
|
|
|
log.Info("Launching System Docker")
|
|
|
|
if !cfg.Debug {
|
|
|
|
output, err := os.Create("/var/log/system-docker.log")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
syscall.Dup2(int(output.Fd()), int(os.Stdout.Fd()))
|
|
|
|
syscall.Dup2(int(output.Fd()), int(os.Stderr.Fd()))
|
|
|
|
}
|
|
|
|
|
|
|
|
os.Stdin.Close()
|
2015-04-16 05:57:59 +00:00
|
|
|
return syscall.Exec(SYSTEM_DOCKER, cfg.SystemDocker.Args, os.Environ())
|
2015-02-09 04:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func MainInit() {
|
|
|
|
if err := RunInit(); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func mountState(cfg *config.Config) error {
|
|
|
|
var err error
|
2015-02-12 22:34:16 +00:00
|
|
|
|
2015-02-17 08:18:48 +00:00
|
|
|
if cfg.State.Dev != "" {
|
|
|
|
dev := util.ResolveDevice(cfg.State.Dev)
|
2015-02-21 07:34:23 +00:00
|
|
|
log.Infof("Mounting state device %s to %s", dev, STATE)
|
2015-02-12 22:34:16 +00:00
|
|
|
|
2015-02-17 08:18:48 +00:00
|
|
|
fsType := cfg.State.FsType
|
|
|
|
if fsType == "auto" {
|
|
|
|
fsType, err = util.GetFsType(dev)
|
2015-02-12 22:34:16 +00:00
|
|
|
}
|
|
|
|
|
2015-02-17 08:18:48 +00:00
|
|
|
if err == nil {
|
|
|
|
log.Debugf("FsType has been set to %s", fsType)
|
|
|
|
err = util.Mount(dev, STATE, fsType, "")
|
2015-02-12 22:34:16 +00:00
|
|
|
}
|
2015-02-09 04:38:37 +00:00
|
|
|
}
|
|
|
|
|
2015-02-17 08:18:48 +00:00
|
|
|
if err != nil && cfg.State.Required {
|
2015-02-12 06:48:32 +00:00
|
|
|
return err
|
|
|
|
}
|
2015-02-09 04:38:37 +00:00
|
|
|
|
2015-02-17 08:18:48 +00:00
|
|
|
if err != nil || cfg.State.Dev == "" {
|
|
|
|
log.Debugf("State will not be persisted")
|
|
|
|
err = util.Mount("none", STATE, "tmpfs", "")
|
|
|
|
}
|
2015-02-09 04:38:37 +00:00
|
|
|
|
2015-02-17 08:18:48 +00:00
|
|
|
return err
|
2015-02-09 04:38:37 +00:00
|
|
|
}
|
|
|
|
|
2015-04-03 21:59:24 +00:00
|
|
|
func createGroups(cfg *config.Config) error {
|
|
|
|
return ioutil.WriteFile("/etc/group", []byte("root:x:0:\n"), 0644)
|
|
|
|
}
|
|
|
|
|
|
|
|
func touchSocket(cfg *config.Config) error {
|
|
|
|
for _, path := range []string{"/var/run/docker.sock", "/var/run/system-docker.sock"} {
|
|
|
|
if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
|
|
|
|
return err
|
|
|
|
}
|
2015-04-16 05:57:59 +00:00
|
|
|
err := ioutil.WriteFile(path, []byte{}, 0700)
|
|
|
|
if err != nil {
|
2015-04-03 21:59:24 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupSystemBridge(cfg *config.Config) error {
|
|
|
|
bridge, cidr := cfg.SystemDocker.BridgeConfig()
|
|
|
|
if bridge == "" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return network.ApplyNetworkConfigs(&config.NetworkConfig{
|
|
|
|
Interfaces: map[string]config.InterfaceConfig{
|
|
|
|
bridge: {
|
|
|
|
Bridge: true,
|
|
|
|
Address: cidr,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-02-09 04:38:37 +00:00
|
|
|
func RunInit() error {
|
|
|
|
var cfg config.Config
|
|
|
|
|
2015-04-03 21:59:24 +00:00
|
|
|
os.Setenv("PATH", "/sbin:/usr/sbin:/usr/bin")
|
2015-02-09 04:38:37 +00:00
|
|
|
os.Setenv("DOCKER_RAMDISK", "true")
|
|
|
|
|
|
|
|
initFuncs := []config.InitFunc{
|
|
|
|
func(cfg *config.Config) error {
|
|
|
|
return createDirs(dirs...)
|
|
|
|
},
|
|
|
|
func(cfg *config.Config) error {
|
2015-02-21 07:34:23 +00:00
|
|
|
log.Info("Setting up mounts")
|
2015-02-09 04:38:37 +00:00
|
|
|
return createMounts(mounts...)
|
|
|
|
},
|
|
|
|
func(cfg *config.Config) error {
|
|
|
|
newCfg, err := config.LoadConfig()
|
2015-02-14 16:34:11 +00:00
|
|
|
if err == nil {
|
2015-02-16 23:38:49 +00:00
|
|
|
newCfg, err = config.LoadConfig()
|
2015-02-14 16:34:11 +00:00
|
|
|
}
|
2015-02-09 04:38:37 +00:00
|
|
|
if err == nil {
|
|
|
|
*cfg = *newCfg
|
|
|
|
}
|
2015-02-14 16:34:11 +00:00
|
|
|
|
|
|
|
if cfg.Debug {
|
2015-03-15 04:27:04 +00:00
|
|
|
cfgString, _ := config.Dump(false, true)
|
2015-02-17 21:31:20 +00:00
|
|
|
if cfgString != "" {
|
|
|
|
log.Debugf("Config: %s", cfgString)
|
|
|
|
}
|
2015-02-14 16:34:11 +00:00
|
|
|
}
|
|
|
|
|
2015-02-09 04:38:37 +00:00
|
|
|
return err
|
|
|
|
},
|
|
|
|
mountCgroups,
|
2015-03-18 13:21:32 +00:00
|
|
|
func(cfg *config.Config) error {
|
|
|
|
return createSymlinks(cfg, symlinks)
|
|
|
|
},
|
2015-04-04 17:17:10 +00:00
|
|
|
createGroups,
|
2015-02-18 01:42:26 +00:00
|
|
|
extractModules,
|
2015-02-09 04:38:37 +00:00
|
|
|
loadModules,
|
2015-03-18 13:21:32 +00:00
|
|
|
setResolvConf,
|
2015-04-03 21:59:24 +00:00
|
|
|
setupSystemBridge,
|
2015-03-18 13:21:32 +00:00
|
|
|
bootstrap,
|
2015-02-09 04:38:37 +00:00
|
|
|
mountState,
|
2015-03-18 13:21:32 +00:00
|
|
|
func(cfg *config.Config) error {
|
|
|
|
return cfg.Reload()
|
|
|
|
},
|
2015-04-28 22:39:27 +00:00
|
|
|
loadModules,
|
2015-03-18 13:21:32 +00:00
|
|
|
setResolvConf,
|
2015-02-21 07:34:23 +00:00
|
|
|
func(cfg *config.Config) error {
|
|
|
|
return createDirs(postDirs...)
|
|
|
|
},
|
2015-02-18 01:42:26 +00:00
|
|
|
func(cfg *config.Config) error {
|
2015-03-18 13:21:32 +00:00
|
|
|
return createMounts(postMounts...)
|
2015-02-18 01:42:26 +00:00
|
|
|
},
|
2015-04-04 17:17:10 +00:00
|
|
|
touchSocket,
|
2015-04-16 05:57:59 +00:00
|
|
|
// Disable R/O root write now to support updating modules
|
|
|
|
//remountRo,
|
2015-02-09 04:38:37 +00:00
|
|
|
sysInit,
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := config.RunInitFuncs(&cfg, initFuncs); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return execDocker(&cfg)
|
|
|
|
}
|