init.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. // +build linux
  2. package init
  3. import (
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "os/exec"
  8. "strings"
  9. "syscall"
  10. log "github.com/Sirupsen/logrus"
  11. "github.com/rancherio/os/cmd/network"
  12. "github.com/rancherio/os/config"
  13. "github.com/rancherio/os/util"
  14. )
  15. const (
  16. STATE string = "/var"
  17. SYSTEM_DOCKER string = "/usr/bin/system-docker"
  18. DOCKER string = "/usr/bin/docker"
  19. SYSINIT string = "/sbin/rancher-sysinit"
  20. )
  21. var (
  22. dirs []string = []string{
  23. "/etc/ssl/certs",
  24. "/sbin",
  25. "/usr/bin",
  26. "/usr/sbin",
  27. }
  28. postDirs []string = []string{
  29. "/var/log",
  30. "/var/lib/rancher/state/home",
  31. "/var/lib/rancher/state/opt",
  32. }
  33. mounts [][]string = [][]string{
  34. {"devtmpfs", "/dev", "devtmpfs", ""},
  35. {"none", "/dev/pts", "devpts", ""},
  36. {"none", "/etc/docker", "tmpfs", ""},
  37. {"none", "/proc", "proc", ""},
  38. {"none", "/run", "tmpfs", ""},
  39. {"none", "/sys", "sysfs", ""},
  40. {"none", "/sys/fs/cgroup", "tmpfs", ""},
  41. }
  42. postMounts [][]string = [][]string{
  43. {"none", "/var/run", "tmpfs", ""},
  44. }
  45. cgroups []string = []string{
  46. "blkio",
  47. "cpu",
  48. "cpuacct",
  49. "cpuset",
  50. "devices",
  51. "freezer",
  52. "memory",
  53. "net_cls",
  54. "perf_event",
  55. }
  56. // Notice this map is the reverse order of a "ln -s x y" command
  57. // so map[y] = x
  58. symlinks map[string]string = map[string]string{
  59. "/etc/ssl/certs/ca-certificates.crt": "/ca.crt",
  60. "/sbin/modprobe": "/busybox",
  61. "/usr/sbin/iptables": "/xtables-multi",
  62. DOCKER: "/docker",
  63. SYSTEM_DOCKER: "/docker",
  64. SYSINIT: "/init",
  65. "/home": "/var/lib/rancher/state/home",
  66. "/opt": "/var/lib/rancher/state/opt",
  67. }
  68. )
  69. func createSymlinks(cfg *config.Config, symlinks map[string]string) error {
  70. log.Debug("Creating symlinking")
  71. for dest, src := range symlinks {
  72. if _, err := os.Stat(dest); os.IsNotExist(err) {
  73. log.Debugf("Symlinking %s => %s", src, dest)
  74. if err = os.Symlink(src, dest); err != nil {
  75. return err
  76. }
  77. }
  78. }
  79. return nil
  80. }
  81. func createDirs(dirs ...string) error {
  82. for _, dir := range dirs {
  83. if _, err := os.Stat(dir); os.IsNotExist(err) {
  84. log.Debugf("Creating %s", dir)
  85. err = os.MkdirAll(dir, 0755)
  86. if err != nil {
  87. return err
  88. }
  89. }
  90. }
  91. return nil
  92. }
  93. func createMounts(mounts ...[]string) error {
  94. for _, mount := range mounts {
  95. log.Debugf("Mounting %s %s %s %s", mount[0], mount[1], mount[2], mount[3])
  96. err := util.Mount(mount[0], mount[1], mount[2], mount[3])
  97. if err != nil {
  98. return err
  99. }
  100. }
  101. return nil
  102. }
  103. func remountRo(cfg *config.Config) error {
  104. log.Info("Remouting root read only")
  105. return util.Remount("/", "ro")
  106. }
  107. func mountCgroups(cfg *config.Config) error {
  108. for _, cgroup := range cgroups {
  109. err := createDirs("/sys/fs/cgroup/" + cgroup)
  110. if err != nil {
  111. return err
  112. }
  113. err = createMounts([][]string{
  114. {"none", "sys/fs/cgroup/" + cgroup, "cgroup", cgroup},
  115. }...)
  116. if err != nil {
  117. return err
  118. }
  119. }
  120. log.Debug("Done mouting cgroupfs")
  121. return nil
  122. }
  123. func extractModules(cfg *config.Config) error {
  124. if _, err := os.Stat(config.MODULES_ARCHIVE); os.IsNotExist(err) {
  125. log.Debug("Modules do not exist")
  126. return nil
  127. }
  128. log.Debug("Extracting modules")
  129. return util.ExtractTar(config.MODULES_ARCHIVE, "/")
  130. }
  131. func setResolvConf(cfg *config.Config) error {
  132. log.Debug("Creating /etc/resolv.conf")
  133. //f, err := os.OpenFile("/etc/resolv.conf", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
  134. f, err := os.Create("/etc/resolv.conf")
  135. if err != nil {
  136. return err
  137. }
  138. defer f.Close()
  139. for _, dns := range cfg.Network.Dns.Nameservers {
  140. content := fmt.Sprintf("nameserver %s\n", dns)
  141. if _, err = f.Write([]byte(content)); err != nil {
  142. return err
  143. }
  144. }
  145. search := strings.Join(cfg.Network.Dns.Search, " ")
  146. if search != "" {
  147. content := fmt.Sprintf("search %s\n", search)
  148. if _, err = f.Write([]byte(content)); err != nil {
  149. return err
  150. }
  151. }
  152. if cfg.Network.Dns.Domain != "" {
  153. content := fmt.Sprintf("domain %s\n", cfg.Network.Dns.Domain)
  154. if _, err = f.Write([]byte(content)); err != nil {
  155. return err
  156. }
  157. }
  158. return nil
  159. }
  160. func loadModules(cfg *config.Config) error {
  161. filesystems, err := ioutil.ReadFile("/proc/filesystems")
  162. if err != nil {
  163. return err
  164. }
  165. if !strings.Contains(string(filesystems), "nodev\toverlay\n") {
  166. log.Debug("Loading overlay module")
  167. err = exec.Command("/sbin/modprobe", "overlay").Run()
  168. if err != nil {
  169. return err
  170. }
  171. }
  172. for _, module := range cfg.Modules {
  173. log.Debugf("Loading module %s", module)
  174. err = exec.Command("/sbin/modprobe", module).Run()
  175. if err != nil {
  176. log.Errorf("Could not load module %s, err %v", module, err)
  177. }
  178. }
  179. return nil
  180. }
  181. func sysInit(cfg *config.Config) error {
  182. args := append([]string{SYSINIT}, os.Args[1:]...)
  183. var cmd *exec.Cmd
  184. if util.IsRunningInTty() {
  185. cmd = exec.Command(args[0], args[1:]...)
  186. cmd.Stdin = os.Stdin
  187. cmd.Stderr = os.Stderr
  188. cmd.Stdout = os.Stdout
  189. } else {
  190. cmd = exec.Command(args[0], args[1:]...)
  191. }
  192. if err := cmd.Start(); err != nil {
  193. return err
  194. }
  195. return os.Stdin.Close()
  196. }
  197. func execDocker(cfg *config.Config) error {
  198. log.Info("Launching System Docker")
  199. if !cfg.Debug {
  200. output, err := os.Create("/var/log/system-docker.log")
  201. if err != nil {
  202. return err
  203. }
  204. syscall.Dup2(int(output.Fd()), int(os.Stdout.Fd()))
  205. syscall.Dup2(int(output.Fd()), int(os.Stderr.Fd()))
  206. }
  207. os.Stdin.Close()
  208. return syscall.Exec(SYSTEM_DOCKER, cfg.SystemDocker.Args, os.Environ())
  209. }
  210. func MainInit() {
  211. if err := RunInit(); err != nil {
  212. log.Fatal(err)
  213. }
  214. }
  215. func mountStateTmpfs(cfg *config.Config) error {
  216. log.Debugf("State will not be persisted")
  217. return util.Mount("none", STATE, "tmpfs", "")
  218. }
  219. func mountState(cfg *config.Config) error {
  220. var err error
  221. if cfg.State.Dev != "" {
  222. dev := util.ResolveDevice(cfg.State.Dev)
  223. if dev == "" {
  224. msg := fmt.Sprintf("Could not resolve device %q", cfg.State.Dev)
  225. log.Infof(msg)
  226. return fmt.Errorf(msg)
  227. }
  228. log.Infof("Mounting state device %s to %s", dev, STATE)
  229. fsType := cfg.State.FsType
  230. if fsType == "auto" {
  231. fsType, err = util.GetFsType(dev)
  232. }
  233. if err == nil {
  234. log.Debugf("FsType has been set to %s", fsType)
  235. err = util.Mount(dev, STATE, fsType, "")
  236. }
  237. } else {
  238. return mountStateTmpfs(cfg)
  239. }
  240. return err
  241. }
  242. func tryMountAndBootstrap(cfg *config.Config) error {
  243. if err := mountState(cfg); err != nil {
  244. if err := bootstrap(cfg); err != nil {
  245. if cfg.State.Required {
  246. return err
  247. }
  248. return mountStateTmpfs(cfg)
  249. }
  250. if err := mountState(cfg); err != nil {
  251. if cfg.State.Required {
  252. return err
  253. }
  254. return mountStateTmpfs(cfg)
  255. }
  256. }
  257. return nil
  258. }
  259. func createGroups(cfg *config.Config) error {
  260. return ioutil.WriteFile("/etc/group", []byte("root:x:0:\n"), 0644)
  261. }
  262. func touchSocket(cfg *config.Config) error {
  263. for _, path := range []string{"/var/run/docker.sock", "/var/run/system-docker.sock"} {
  264. if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
  265. return err
  266. }
  267. err := ioutil.WriteFile(path, []byte{}, 0700)
  268. if err != nil {
  269. return err
  270. }
  271. }
  272. return nil
  273. }
  274. func setupSystemBridge(cfg *config.Config) error {
  275. bridge, cidr := cfg.SystemDocker.BridgeConfig()
  276. if bridge == "" {
  277. return nil
  278. }
  279. return network.ApplyNetworkConfigs(&config.NetworkConfig{
  280. Interfaces: map[string]config.InterfaceConfig{
  281. bridge: {
  282. Bridge: true,
  283. Address: cidr,
  284. },
  285. },
  286. })
  287. }
  288. func RunInit() error {
  289. var cfg config.Config
  290. os.Setenv("PATH", "/sbin:/usr/sbin:/usr/bin")
  291. os.Setenv("DOCKER_RAMDISK", "true")
  292. initFuncs := []config.InitFunc{
  293. func(cfg *config.Config) error {
  294. return createDirs(dirs...)
  295. },
  296. func(cfg *config.Config) error {
  297. log.Info("Setting up mounts")
  298. return createMounts(mounts...)
  299. },
  300. func(cfg *config.Config) error {
  301. newCfg, err := config.LoadConfig()
  302. if err == nil {
  303. newCfg, err = config.LoadConfig()
  304. }
  305. if err == nil {
  306. *cfg = *newCfg
  307. }
  308. if cfg.Debug {
  309. cfgString, _ := config.Dump(false, true)
  310. if cfgString != "" {
  311. log.Debugf("Config: %s", cfgString)
  312. }
  313. }
  314. return err
  315. },
  316. mountCgroups,
  317. func(cfg *config.Config) error {
  318. return createSymlinks(cfg, symlinks)
  319. },
  320. createGroups,
  321. extractModules,
  322. loadModules,
  323. setResolvConf,
  324. setupSystemBridge,
  325. tryMountAndBootstrap,
  326. func(cfg *config.Config) error {
  327. return cfg.Reload()
  328. },
  329. loadModules,
  330. setResolvConf,
  331. func(cfg *config.Config) error {
  332. return createDirs(postDirs...)
  333. },
  334. func(cfg *config.Config) error {
  335. return createMounts(postMounts...)
  336. },
  337. touchSocket,
  338. // Disable R/O root write now to support updating modules
  339. //remountRo,
  340. sysInit,
  341. }
  342. if err := config.RunInitFuncs(&cfg, initFuncs); err != nil {
  343. return err
  344. }
  345. return execDocker(&cfg)
  346. }