mirror of
https://github.com/rancher/os.git
synced 2025-04-28 19:34:45 +00:00
172 lines
4.6 KiB
Go
172 lines
4.6 KiB
Go
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()
|
|
}
|