123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- package sysinit
- import (
- "fmt"
- "io/ioutil"
- "os"
- "os/exec"
- "path"
- "path/filepath"
- "strings"
- "syscall"
- "github.com/rancher/os/cmd/control"
- "github.com/rancher/os/config"
- "github.com/rancher/os/pkg/compose"
- "github.com/rancher/os/pkg/docker"
- "github.com/rancher/os/pkg/log"
- "github.com/docker/engine-api/types"
- "github.com/docker/libcompose/project/options"
- "golang.org/x/net/context"
- )
- const (
- systemImagesPreloadDirectory = "/var/lib/rancher/preload/system-docker"
- systemImagesLoadStamp = "/var/lib/rancher/.sysimages_%s_loaded.done"
- )
- func hasImage(name string) bool {
- stamp := path.Join(config.StateDir, name)
- if _, err := os.Stat(stamp); os.IsNotExist(err) {
- return false
- }
- return true
- }
- func getImagesArchive(bootstrap bool) string {
- var archive string
- if bootstrap {
- archive = path.Join(config.ImagesPath, config.InitImages)
- } else {
- archive = path.Join(config.ImagesPath, config.SystemImages)
- }
- return archive
- }
- func LoadBootstrapImages(cfg *config.CloudConfig) (*config.CloudConfig, error) {
- return loadImages(cfg, true)
- }
- func LoadSystemImages(cfg *config.CloudConfig) (*config.CloudConfig, error) {
- stamp := fmt.Sprintf(systemImagesLoadStamp, strings.Replace(config.Version, ".", "_", -1))
- if _, err := os.Stat(stamp); os.IsNotExist(err) {
- os.Create(stamp)
- return loadImages(cfg, false)
- }
- log.Infof("Skipped loading system images because %s exists", systemImagesLoadStamp)
- return cfg, nil
- }
- func loadImages(cfg *config.CloudConfig, bootstrap bool) (*config.CloudConfig, error) {
- archive := getImagesArchive(bootstrap)
- client, err := docker.NewSystemClient()
- if err != nil {
- return cfg, err
- }
- if !hasImage(filepath.Base(archive)) {
- if _, err := os.Stat(archive); os.IsNotExist(err) {
- log.Fatalf("FATAL: Could not load images from %s (file not found)", archive)
- }
- // client.ImageLoad is an asynchronous operation
- // To ensure the order of execution, use cmd instead of it
- log.Infof("Loading images from %s", archive)
- cmd := exec.Command("/usr/bin/system-docker", "load", "-q", "-i", archive)
- if out, err := cmd.CombinedOutput(); err != nil {
- log.Fatalf("FATAL: Error loading images from %s (%v)\n%s ", archive, err, out)
- }
- log.Infof("Done loading images from %s", archive)
- }
- dockerImages, _ := client.ImageList(context.Background(), types.ImageListOptions{})
- for _, dimg := range dockerImages {
- log.Debugf("Loaded a docker image: %s", dimg.RepoTags)
- }
- return cfg, nil
- }
- func SysInit() error {
- cfg := config.LoadConfig()
- if err := control.PreloadImages(docker.NewSystemClient, systemImagesPreloadDirectory); err != nil {
- log.Errorf("Failed to preload System Docker images: %v", err)
- }
- _, err := config.ChainCfgFuncs(cfg,
- config.CfgFuncs{
- {"loadSystemImages", LoadSystemImages},
- {"start project", func(cfg *config.CloudConfig) (*config.CloudConfig, error) {
- p, err := compose.GetProject(cfg, false, true)
- if err != nil {
- return cfg, err
- }
- return cfg, p.Up(context.Background(), options.Up{
- Create: options.Create{
- NoRecreate: true,
- },
- Log: cfg.Rancher.Log,
- })
- }},
- {"sync", func(cfg *config.CloudConfig) (*config.CloudConfig, error) {
- syscall.Sync()
- return cfg, nil
- }},
- {"banner", func(cfg *config.CloudConfig) (*config.CloudConfig, error) {
- log.Infof("RancherOS %s started", config.Version)
- return cfg, nil
- }}})
- return err
- }
- func loadServicesCache() {
- // this code make sure the open-vm-tools, modem-manager... services can be started correct when there is no network
- // make sure the cache directory exist
- if err := os.MkdirAll("/var/lib/rancher/cache/", os.ModeDir|0755); err != nil {
- log.Errorf("Create service cache diretory error: %v", err)
- }
- // move os-services cache file
- if _, err := os.Stat("/usr/share/ros/services-cache"); err == nil {
- files, err := ioutil.ReadDir("/usr/share/ros/services-cache/")
- if err != nil {
- log.Errorf("Read file error: %v", err)
- }
- for _, f := range files {
- err := os.Rename("/usr/share/ros/services-cache/"+f.Name(), "/var/lib/rancher/cache/"+f.Name())
- if err != nil {
- log.Errorf("Rename file error: %v", err)
- }
- }
- if err := os.Remove("/usr/share/ros/services-cache"); err != nil {
- log.Errorf("Remove file error: %v", err)
- }
- }
- }
- func RunSysInit(c *config.CloudConfig) (*config.CloudConfig, error) {
- loadServicesCache()
- args := append([]string{config.SysInitBin}, os.Args[1:]...)
- cmd := &exec.Cmd{
- Path: config.RosBin,
- Args: args,
- }
- cmd.Stdin = os.Stdin
- cmd.Stderr = os.Stderr
- cmd.Stdout = os.Stdout
- if err := cmd.Start(); err != nil {
- return c, err
- }
- return c, os.Stdin.Close()
- }
|