mirror of
https://github.com/rancher/os.git
synced 2025-08-07 17:54:12 +00:00
Initial commit
This commit is contained in:
commit
df4a126175
3
.dockerignore
Normal file
3
.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.git
|
||||||
|
build
|
||||||
|
dist
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/bin
|
||||||
|
/build
|
||||||
|
/dist
|
||||||
|
/gopath
|
||||||
|
.dockerfile
|
||||||
|
*.swp
|
||||||
|
Dockerfile
|
1
.wrap-docker-args
Normal file
1
.wrap-docker-args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--privileged
|
1
Godeps/_workspace/src/github.com/Sirupsen/logrus
generated
vendored
Submodule
1
Godeps/_workspace/src/github.com/Sirupsen/logrus
generated
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 0b189e019aabcec0af8e433b10b3073ad9382b44
|
1
Godeps/_workspace/src/github.com/docker/docker
generated
vendored
Submodule
1
Godeps/_workspace/src/github.com/docker/docker
generated
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c61e97c728e551efbdad6f81eb0118da4269fa88
|
1
Godeps/_workspace/src/github.com/fsouza/go-dockerclient
generated
vendored
Submodule
1
Godeps/_workspace/src/github.com/fsouza/go-dockerclient
generated
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 57da4a6dd45ab6d734c466e28253182d8467e335
|
1
Godeps/_workspace/src/github.com/kless/term
generated
vendored
Submodule
1
Godeps/_workspace/src/github.com/kless/term
generated
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit d57d9d2d5be197e12d9dee142d855470d83ce62f
|
BIN
assets/empty-hd.img.gz
Normal file
BIN
assets/empty-hd.img.gz
Normal file
Binary file not shown.
10
build.sh
Executable file
10
build.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd $(dirname $0)
|
||||||
|
|
||||||
|
export DOCKER_IMAGE=rancher-os-build
|
||||||
|
|
||||||
|
./scripts/ci
|
||||||
|
mkdir -p dist
|
||||||
|
docker run -it -e CHOWN_ID=$(id -u) -v $(pwd)/dist:/source/target $DOCKER_IMAGE
|
237
config/config.go
Normal file
237
config/config.go
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InitFunc func(*Config) error
|
||||||
|
|
||||||
|
type ContainerConfig struct {
|
||||||
|
Options []string `json:"options,omitempty"`
|
||||||
|
Image string `json:"image,omitempty"`
|
||||||
|
Args []string `json:"args,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
BootstrapContainers []ContainerConfig `json:"bootstrapContainers,omitempty"`
|
||||||
|
Debug bool `json:"debug,omitempty"`
|
||||||
|
DockerEndpoint string `json:"dockerEndpoint,omitempty"`
|
||||||
|
Dns []string `json:"dns,omitempty"`
|
||||||
|
ImagesPath string `json:"ImagesPath,omitempty"`
|
||||||
|
ImagesPattern string `json:"ImagesPattern,omitempty"`
|
||||||
|
ModulesArchive string `json:"modulesArchive,omitempty"`
|
||||||
|
Rescue bool `json:"rescue,omitempty"`
|
||||||
|
RescueContainer ContainerConfig `json:"rescueContainer,omitempty"`
|
||||||
|
StateDevFSType string `json:"stateDeviceFsType,omitempty"`
|
||||||
|
StateDev string `json:"stateDevice,omitempty"`
|
||||||
|
StateRequired bool `json:"stateRequired,omitempty"`
|
||||||
|
SysInit string `json:"sysInit,omitempty"`
|
||||||
|
SystemContainers []ContainerConfig `json:"systemContainers,omitempty"`
|
||||||
|
SystemDockerArgs []string `json:"systemDockerArgs,omitempty"`
|
||||||
|
UserContainers []ContainerConfig `json:"userContainser,omitempty"`
|
||||||
|
UserInit string `json:"userInit,omitempty"`
|
||||||
|
DockerBin string `json:"dockerBin,omitempty"`
|
||||||
|
Modules []string `json:"modules,omitempty"`
|
||||||
|
Respawn []string `json:"respawn,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadConfig() (*Config, error) {
|
||||||
|
cfg := NewConfig()
|
||||||
|
if err := cfg.Reload(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Debug {
|
||||||
|
log.SetLevel(log.DebugLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig() *Config {
|
||||||
|
return &Config{
|
||||||
|
DockerBin: "/usr/bin/docker",
|
||||||
|
Debug: true,
|
||||||
|
DockerEndpoint: "unix:/var/run/docker.sock",
|
||||||
|
Dns: []string{
|
||||||
|
"8.8.8.8",
|
||||||
|
"8.8.4.4",
|
||||||
|
},
|
||||||
|
ImagesPath: "/",
|
||||||
|
ImagesPattern: "images*.tar",
|
||||||
|
StateRequired: false,
|
||||||
|
//StateDev: "/dev/sda",
|
||||||
|
StateDevFSType: "ext4",
|
||||||
|
SysInit: "/sbin/init-sys",
|
||||||
|
SystemDockerArgs: []string{"docker", "-d", "-s", "overlay", "-b", "none"},
|
||||||
|
UserInit: "/sbin/init-user",
|
||||||
|
Modules: []string{},
|
||||||
|
ModulesArchive: "/modules.tar",
|
||||||
|
SystemContainers: []ContainerConfig{
|
||||||
|
{
|
||||||
|
Options: []string{
|
||||||
|
"--name", "system-state",
|
||||||
|
"--net", "none",
|
||||||
|
"--read-only",
|
||||||
|
},
|
||||||
|
Image: "state",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Options: []string{
|
||||||
|
"--net", "none",
|
||||||
|
"--privileged",
|
||||||
|
"--rm",
|
||||||
|
"--volume", "/dev:/host/dev",
|
||||||
|
"--volume", "/lib/modules:/lib/modules:ro",
|
||||||
|
},
|
||||||
|
Image: "udev",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Options: []string{
|
||||||
|
"--cap-add", "NET_ADMIN",
|
||||||
|
"--net", "host",
|
||||||
|
"--rm",
|
||||||
|
},
|
||||||
|
Image: "network",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Options: []string{
|
||||||
|
"-d",
|
||||||
|
"--restart", "always",
|
||||||
|
"--net", "host",
|
||||||
|
"--privileged",
|
||||||
|
"--volume", "/lib/modules:/lib/modules:ro",
|
||||||
|
"--volume", "/usr/bin/docker:/usr/bin/docker:ro",
|
||||||
|
"--volumes-from", "system-state",
|
||||||
|
},
|
||||||
|
Image: "userdocker",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Options: []string{
|
||||||
|
"--rm",
|
||||||
|
"--privileged",
|
||||||
|
"--volume", "/:/host:ro",
|
||||||
|
"--volume", "/lib/modules:/lib/modules:ro",
|
||||||
|
"--volume", "/usr/bin/docker:/usr/bin/docker:ro",
|
||||||
|
"--volume", "/usr/bin/system-docker:/usr/bin/system-docker:ro",
|
||||||
|
"--volume", "/var/run/docker.sock:/var/run/system-docker.sock:ro",
|
||||||
|
"--volumes-from", "system-state",
|
||||||
|
"--net", "host",
|
||||||
|
"--pid", "host",
|
||||||
|
"-it",
|
||||||
|
},
|
||||||
|
Image: "console",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RescueContainer: ContainerConfig{
|
||||||
|
Options: []string{
|
||||||
|
"--rm",
|
||||||
|
"--privileged",
|
||||||
|
"--volume", "/:/host",
|
||||||
|
"--volume", "/lib/modules:/lib/modules:ro",
|
||||||
|
"--volume", "/usr/bin/docker:/usr/bin/docker:ro",
|
||||||
|
"--volume", "/var/run/docker.sock:/var/run/docker.sock:ro",
|
||||||
|
"--net", "host",
|
||||||
|
"--pid", "host",
|
||||||
|
"-it",
|
||||||
|
},
|
||||||
|
Image: "rescue",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) readCmdline() error {
|
||||||
|
cmdLine, err := ioutil.ReadFile("/proc/cmdline")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdLineObj := parseCmdline(strings.TrimSpace(string(cmdLine)))
|
||||||
|
|
||||||
|
// Lazy way to assign values to *Config
|
||||||
|
b, err := json.Marshal(cmdLineObj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return json.Unmarshal(b, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dummyMarshall(value string) interface{} {
|
||||||
|
if value == "true" {
|
||||||
|
return true
|
||||||
|
} else if value == "false" {
|
||||||
|
return false
|
||||||
|
} else if ok, _ := regexp.MatchString("^[0-9]+$", value); ok {
|
||||||
|
i, err := strconv.Atoi(value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCmdline(cmdLine string) map[string]interface{} {
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
|
||||||
|
outer:
|
||||||
|
for _, part := range strings.Split(cmdLine, " ") {
|
||||||
|
if !strings.HasPrefix(part, "rancher.") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var value string
|
||||||
|
kv := strings.SplitN(part, "=", 2)
|
||||||
|
|
||||||
|
if len(kv) == 1 {
|
||||||
|
value = "true"
|
||||||
|
} else {
|
||||||
|
value = kv[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
current := result
|
||||||
|
keys := strings.Split(kv[0], ".")[1:]
|
||||||
|
for i, key := range keys {
|
||||||
|
if i == len(keys)-1 {
|
||||||
|
current[key] = dummyMarshall(value)
|
||||||
|
} else {
|
||||||
|
if obj, ok := current[key]; ok {
|
||||||
|
if newCurrent, ok := obj.(map[string]interface{}); ok {
|
||||||
|
current = newCurrent
|
||||||
|
} else {
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newCurrent := make(map[string]interface{})
|
||||||
|
current[key] = newCurrent
|
||||||
|
current = newCurrent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) Reload() error {
|
||||||
|
return c.readCmdline()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunInitFuncs(cfg *Config, initFuncs []InitFunc) error {
|
||||||
|
for i, initFunc := range initFuncs {
|
||||||
|
log.Debugf("[%d/%d] Starting", i+1, len(initFuncs))
|
||||||
|
if err := initFunc(cfg); err != nil {
|
||||||
|
log.Errorf("Failed [%d/%d] %d%%", i+1, len(initFuncs), ((i + 1) * 100 / len(initFuncs)))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugf("[%d/%d] Done %d%%", i+1, len(initFuncs), ((i + 1) * 100 / len(initFuncs)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
29
config/config_test.go
Normal file
29
config/config_test.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.google.com/p/rog-go/deepdiff"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseCmdline(t *testing.T) {
|
||||||
|
expected := map[string]interface{}{
|
||||||
|
"rescue": true,
|
||||||
|
"key1": "value1",
|
||||||
|
"key2": "value2",
|
||||||
|
"obj1": map[string]interface{}{
|
||||||
|
"key3": "3value",
|
||||||
|
"obj2": map[string]interface{}{
|
||||||
|
"key4": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"key5": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := parseCmdline("a b rancher.rescue rancher.key1=value1 c rancher.key2=value2 rancher.obj1.key3=3value rancher.obj1.obj2.key4 rancher.key5=5")
|
||||||
|
|
||||||
|
ok, err := deepdiff.DeepDiff(actual, expected)
|
||||||
|
if !ok || err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
35
docker/client.go
Normal file
35
docker/client.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
dockerClient "github.com/fsouza/go-dockerclient"
|
||||||
|
"github.com/rancherio/os/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MAX_WAIT = 30000
|
||||||
|
INTERVAL = 100
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewClient(cfg *config.Config) (*dockerClient.Client, error) {
|
||||||
|
client, err := dockerClient.NewClient(cfg.DockerEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < (MAX_WAIT / INTERVAL); i++ {
|
||||||
|
_, err = client.Info()
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(INTERVAL * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
289
init/init.go
Normal file
289
init/init.go
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
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 (
|
||||||
|
STATE string = "/var/lib/rancher/state"
|
||||||
|
DOCKER string = "/var/lib/docker"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
dirs []string = []string{
|
||||||
|
"/bin",
|
||||||
|
"/dev",
|
||||||
|
"/dev/pts",
|
||||||
|
"/etc/ssl/certs/ca-certificates.crt",
|
||||||
|
"/proc",
|
||||||
|
"/sbin",
|
||||||
|
"/sys",
|
||||||
|
"/usr/bin",
|
||||||
|
DOCKER,
|
||||||
|
STATE,
|
||||||
|
"/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 {
|
||||||
|
cmd := exec.Command("openvt", "-s", "/sbin/init-sys")
|
||||||
|
//cmd := exec.Command("/sbin/init-sys")
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
//log.Debug("Launching host console")
|
||||||
|
//return exec.Command("openvt", "/bin/sh").Run()
|
||||||
|
|
||||||
|
//log.Debug("Launching console")
|
||||||
|
//return exec.Command("/bin/openvt", "-s", "/bin/console-container.sh").Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func execDocker(cfg *config.Config) error {
|
||||||
|
log.Info("Launching Docker")
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
if err == nil {
|
||||||
|
*cfg = *newCfg
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
createSymlinks,
|
||||||
|
setResolvConf,
|
||||||
|
extractModules,
|
||||||
|
remountRo,
|
||||||
|
mountCgroups,
|
||||||
|
loadModules,
|
||||||
|
mountState,
|
||||||
|
sysInit,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := config.RunInitFuncs(&cfg, initFuncs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return execDocker(&cfg)
|
||||||
|
}
|
24
main.go
Normal file
24
main.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
osInit "github.com/rancherio/os/init"
|
||||||
|
"github.com/rancherio/os/sysinit"
|
||||||
|
"github.com/rancherio/os/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
reexec.Register("init", osInit.MainInit)
|
||||||
|
reexec.Register("/init", osInit.MainInit)
|
||||||
|
reexec.Register("./init", osInit.MainInit)
|
||||||
|
reexec.Register("/sbin/init-sys", sysinit.SysInit)
|
||||||
|
reexec.Register("/usr/bin/system-docker", user.SystemDocker)
|
||||||
|
reexec.Register("system-docker", user.SystemDocker)
|
||||||
|
|
||||||
|
if !reexec.Init() {
|
||||||
|
log.Fatalf("Failed to find an entry point for %s", os.Args[0])
|
||||||
|
}
|
||||||
|
}
|
15
scripts/bootstrap
Executable file
15
scripts/bootstrap
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y curl rsync build-essential syslinux xorriso
|
||||||
|
|
||||||
|
|
||||||
|
curl -sL https://test.docker.com/builds/Linux/x86_64/docker-1.5.0-rc4 > /usr/bin/docker
|
||||||
|
|
||||||
|
chmod +x /usr/bin/docker
|
||||||
|
|
||||||
|
curl -sL https://storage.googleapis.com/golang/go1.4.1.linux-amd64.tar.gz | tar xvzf - -C /usr/local
|
29
scripts/build
Executable file
29
scripts/build
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
if [[ ! -x "$(which go)" && -x /usr/local/go/bin/go ]]; then
|
||||||
|
PATH=/usr/local/go/bin:${PATH}
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
if [ -f ./build/bootstrap.envs ];then
|
||||||
|
. ./build/bootstrap.envs
|
||||||
|
fi
|
||||||
|
|
||||||
|
export GOPATH=$(pwd)/Godeps/_workspace:$(pwd)/gopath
|
||||||
|
|
||||||
|
PACKAGE=./gopath/src/$(<.package)
|
||||||
|
|
||||||
|
if [ -L ${PACKAGE} ]; then
|
||||||
|
rm ${PACKAGE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ${PACKAGE} ]; then
|
||||||
|
mkdir -p $(dirname $PACKAGE)
|
||||||
|
ln -s $(pwd) $PACKAGE
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo export GOPATH=$GOPATH
|
||||||
|
|
||||||
|
mkdir -p bin
|
||||||
|
go build -ldflags "-linkmode external -extldflags -static" -o bin/rancheros
|
125
scripts/build-common
Normal file
125
scripts/build-common
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
: ${ARTIFACTS:=$(pwd)/assets}
|
||||||
|
: ${BUILD:=$(pwd)/build}
|
||||||
|
: ${CONFIG:=$(pwd)/config}
|
||||||
|
: ${DIST:=$(pwd)/dist}
|
||||||
|
|
||||||
|
BUILDROOT=buildroot-2014.11.tar.bz2
|
||||||
|
DOCKER_FILE=${CONFIG}/.dockerfile
|
||||||
|
|
||||||
|
mkdir -p ${BUILD} ${DIST}
|
||||||
|
|
||||||
|
busybox_install()
|
||||||
|
{
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y build-essential wget libncurses5-dev unzip bc
|
||||||
|
|
||||||
|
cd ${BUILD}
|
||||||
|
|
||||||
|
rm -rf ${BUILDROOT/.tar.bz2//}
|
||||||
|
tar xvjf ${ARTIFACTS}/${BUILDROOT}
|
||||||
|
cd ${BUILDROOT/.tar.bz2//}
|
||||||
|
|
||||||
|
cp $1 .config
|
||||||
|
make oldconfig
|
||||||
|
make
|
||||||
|
|
||||||
|
cp output/images/rootfs.tar $2
|
||||||
|
}
|
||||||
|
|
||||||
|
write_base()
|
||||||
|
{
|
||||||
|
if [ "${BASE_WRITTEN}" = "true" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p $(dirname ${DOCKER_FILE})
|
||||||
|
|
||||||
|
cat > ${DOCKER_FILE} << EOF
|
||||||
|
FROM ${DOCKER_BASE:=ubuntu:14.04.1}
|
||||||
|
ENV TERM xterm
|
||||||
|
WORKDIR /source
|
||||||
|
CMD ["/source/scripts/install"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
BASE_WRITTEN=true
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
local content
|
||||||
|
|
||||||
|
while [ $# -gt 1 ]; do
|
||||||
|
case $1 in
|
||||||
|
--assets)
|
||||||
|
shift 1
|
||||||
|
if [ -e "$1" ]; then
|
||||||
|
content="$content\nCOPY $1 /source/$1"
|
||||||
|
else
|
||||||
|
content="$content\nCOPY $1 /source/"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift 1
|
||||||
|
done
|
||||||
|
|
||||||
|
write_base
|
||||||
|
if [ -n "$content" ]; then
|
||||||
|
echo -e "$content" >> ${DOCKER_FILE}
|
||||||
|
fi
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
echo -e "\nCOPY $1 /source/$1" >> ${DOCKER_FILE}
|
||||||
|
echo -e "RUN /source/$1" >> ${DOCKER_FILE}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
finish()
|
||||||
|
{
|
||||||
|
local cmd="docker build -t ${DOCKER_IMAGE} -f ${DOCKER_FILE} ."
|
||||||
|
echo Running $cmd
|
||||||
|
echo Pwd $(pwd)
|
||||||
|
|
||||||
|
cat ${DOCKER_FILE}
|
||||||
|
|
||||||
|
$cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_docker_build()
|
||||||
|
{
|
||||||
|
BASE_WRITTEN=false
|
||||||
|
}
|
||||||
|
|
||||||
|
check()
|
||||||
|
{
|
||||||
|
local hash=$1
|
||||||
|
local file=$2
|
||||||
|
|
||||||
|
if [ ! -e "$file" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CURRENT=$(sha1sum $file | awk '{print $1}')
|
||||||
|
|
||||||
|
[ "$hash" = "$CURRENT" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
download()
|
||||||
|
{
|
||||||
|
mkdir -p ${ARTIFACTS}
|
||||||
|
|
||||||
|
local url=$2
|
||||||
|
local file=${ARTIFACTS}/$(basename $2)
|
||||||
|
local hash=$1
|
||||||
|
|
||||||
|
if ! check $hash $file; then
|
||||||
|
curl -sL $url > $file
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! check $hash $file; then
|
||||||
|
echo "ERROR: $file does not match checksum $hash, got $CURRENT" 1>&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
53
scripts/build-images
Executable file
53
scripts/build-images
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
source scripts/build-common
|
||||||
|
|
||||||
|
mkdir -p ${BUILD}/initrd ${DIST}/artifacts
|
||||||
|
|
||||||
|
echo Extracting ${ARTIFACTS}/os-base.tar.xz
|
||||||
|
tar xJf ${ARTIFACTS}/os-base.tar.xz -C ${BUILD}
|
||||||
|
|
||||||
|
cp /etc/ssl/certs/ca-certificates.crt ${BUILD}/ca.crt
|
||||||
|
|
||||||
|
rm -rf ${BUILD}/initrd/lib
|
||||||
|
cp -rf ${BUILD}/dist/kernel/lib ${BUILD}/initrd
|
||||||
|
(
|
||||||
|
cd ${BUILD}/initrd/lib/modules
|
||||||
|
# Taken from boot2docker
|
||||||
|
# Remove useless kernel modules, based on unclejack/debian2docker
|
||||||
|
rm -rf ./*/kernel/sound/*
|
||||||
|
rm -rf ./*/kernel/drivers/gpu/*
|
||||||
|
rm -rf ./*/kernel/drivers/infiniband/*
|
||||||
|
rm -rf ./*/kernel/drivers/isdn/*
|
||||||
|
rm -rf ./*/kernel/drivers/media/*
|
||||||
|
rm -rf ./*/kernel/drivers/staging/lustre/*
|
||||||
|
rm -rf ./*/kernel/drivers/staging/comedi/*
|
||||||
|
rm -rf ./*/kernel/fs/ocfs2/*
|
||||||
|
rm -rf ./*/kernel/net/bluetooth/*
|
||||||
|
rm -rf ./*/kernel/net/mac80211/*
|
||||||
|
rm -rf ./*/kernel/net/wireless/*
|
||||||
|
)
|
||||||
|
cp -f ${ARTIFACTS}/docker* ${BUILD}/initrd/docker
|
||||||
|
chmod +x ${BUILD}/initrd/docker
|
||||||
|
|
||||||
|
cp ${BUILD}/dist/kernel/bzImage ${DIST}/artifacts/vmlinuz
|
||||||
|
|
||||||
|
tar xf ${BUILD}/dist/rootfs-static.tar -C ${BUILD}/initrd --strip-components=2 ./bin/busybox
|
||||||
|
|
||||||
|
if ! docker info >/dev/null 2>&1 && [ -x "$(which wrapdocker)" ]; then
|
||||||
|
wrapdocker
|
||||||
|
fi
|
||||||
|
|
||||||
|
>${BUILD}/tags
|
||||||
|
for i in scripts/dockerimages/[0-9]*; do
|
||||||
|
tag=$(echo $i | cut -f2 -d-)
|
||||||
|
echo Building $tag
|
||||||
|
docker build -t $tag -f $i .
|
||||||
|
echo $tag >> ${BUILD}/tags
|
||||||
|
done
|
||||||
|
|
||||||
|
echo Creating images.tar
|
||||||
|
docker save $(<${BUILD}/tags) > ${BUILD}/initrd/images.tar
|
48
scripts/ci
Executable file
48
scripts/ci
Executable file
@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
export DOCKER_IMAGE=${DOCKER_IMAGE:=rancher-os-build}
|
||||||
|
export DOCKER_BASE=rancher/docker-dind-base:latest
|
||||||
|
|
||||||
|
source scripts/build-common
|
||||||
|
|
||||||
|
DOCKER_FILE=$(pwd)/.dockerfile
|
||||||
|
|
||||||
|
generate_images()
|
||||||
|
{
|
||||||
|
IMAGE_ID=$(docker images --no-trunc -q ${DOCKER_IMAGE})
|
||||||
|
|
||||||
|
if [ -e ${BUILD}/${IMAGE_ID} ]; then
|
||||||
|
DOCKER_BASE=$(<${BUILD}/${IMAGE_ID})
|
||||||
|
else
|
||||||
|
CID=$(docker run -d --privileged ${DOCKER_IMAGE} /source/scripts/build-images)
|
||||||
|
docker logs -f ${CID} &
|
||||||
|
trap "docker rm -f ${CID}" exit
|
||||||
|
docker wait $CID
|
||||||
|
DOCKER_BASE=$(docker commit $CID)
|
||||||
|
|
||||||
|
echo ${DOCKER_BASE} > ${BUILD}/${IMAGE_ID}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run ./scripts/bootstrap
|
||||||
|
run --assets ./scripts/build-common ./scripts/download
|
||||||
|
run --assets ./scripts/dockerimages --assets ./scripts/build-images
|
||||||
|
finish
|
||||||
|
|
||||||
|
generate_images
|
||||||
|
|
||||||
|
reset_docker_build
|
||||||
|
ARGS=
|
||||||
|
for i in $(ls -d * .* | sort -u | grep -Ev '(\.|\.\.|\.dockerfile|build|dist|.git|scripts|bin)$'); do
|
||||||
|
if [ -d $i ]; then
|
||||||
|
run --assets $i
|
||||||
|
else
|
||||||
|
ARGS="${ARGS} $i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
run --assets "${ARGS}" ./scripts/build
|
||||||
|
run --assets ./scripts/install ./scripts/package
|
||||||
|
finish
|
5
scripts/clean
Executable file
5
scripts/clean
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
rm -rf build dist
|
3
scripts/dockerimages/00-base
Normal file
3
scripts/dockerimages/00-base
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
FROM scratch
|
||||||
|
ADD build/dist/rootfs.tar /
|
||||||
|
CMD ["/bin/sh"]
|
5
scripts/dockerimages/01-state
Normal file
5
scripts/dockerimages/01-state
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
FROM base
|
||||||
|
VOLUME /home
|
||||||
|
VOLUME /var/lib/docker
|
||||||
|
VOLUME /var/run
|
||||||
|
CMD ["echo"]
|
3
scripts/dockerimages/02-udev
Normal file
3
scripts/dockerimages/02-udev
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
FROM base
|
||||||
|
COPY scripts/dockerimages/scripts/udev.sh /
|
||||||
|
CMD ["/udev.sh"]
|
2
scripts/dockerimages/03-network
Normal file
2
scripts/dockerimages/03-network
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FROM base
|
||||||
|
CMD ["udhcpc", "-i", "eth0"]
|
4
scripts/dockerimages/04-userdocker
Normal file
4
scripts/dockerimages/04-userdocker
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
FROM base
|
||||||
|
COPY scripts/dockerimages/scripts/docker.sh /
|
||||||
|
COPY build/ca.crt /etc/ssl/certs/ca-certificates.crt
|
||||||
|
CMD ["/docker.sh"]
|
2
scripts/dockerimages/05-console
Normal file
2
scripts/dockerimages/05-console
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FROM base
|
||||||
|
CMD ["/bin/sh"]
|
2
scripts/dockerimages/06-rescue
Normal file
2
scripts/dockerimages/06-rescue
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FROM console
|
||||||
|
CMD ["/bin/sh"]
|
19
scripts/dockerimages/scripts/docker.sh
Executable file
19
scripts/dockerimages/scripts/docker.sh
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -x -e
|
||||||
|
|
||||||
|
CGROUPS="perf_event net_cls freezer devices blkio memory cpuacct cpu cpuset"
|
||||||
|
|
||||||
|
mkdir -p /sys/fs/cgroup
|
||||||
|
mount -t tmpfs none /sys/fs/cgroup
|
||||||
|
|
||||||
|
for i in $CGROUPS; do
|
||||||
|
mkdir -p /sys/fs/cgroup/$i
|
||||||
|
mount -t cgroup -o $i none /sys/fs/cgroup/$i
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! lsmod | grep -q br_netfilter; then
|
||||||
|
modprobe br_netfilter
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f /var/run/docker.pid
|
||||||
|
exec docker -d -s overlay
|
4
scripts/dockerimages/scripts/os-dockerfile
Normal file
4
scripts/dockerimages/scripts/os-dockerfile
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
FROM scratch
|
||||||
|
COPY init busybox docker images.tar /
|
||||||
|
COPY lib /lib
|
||||||
|
CMD ["/init"]
|
6
scripts/dockerimages/scripts/udev.sh
Executable file
6
scripts/dockerimages/scripts/udev.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
mount --bind /host/dev /dev
|
||||||
|
udevd --daemon
|
||||||
|
udevadm trigger --action=add
|
||||||
|
udevadm settle
|
8
scripts/download
Executable file
8
scripts/download
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
source scripts/build-common
|
||||||
|
|
||||||
|
download a8e5925eab10a472af4b9326dc3ff1068fd56886 https://github.com/rancherio/os-base/releases/download/v0.0.1/os-base.tar.xz
|
||||||
|
download c7d977c2bdc48c022fcf3a51a6e26229247cfb15 https://test.docker.com/builds/Linux/x86_64/docker-1.5.0-rc4
|
11
scripts/install
Executable file
11
scripts/install
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -x
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
. scripts/build-common
|
||||||
|
|
||||||
|
mkdir -p target
|
||||||
|
rm -rf target/artifacts
|
||||||
|
|
||||||
|
cp -rf ${DIST}/artifacts target
|
42
scripts/package
Executable file
42
scripts/package
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
source scripts/build-common
|
||||||
|
|
||||||
|
cp bin/rancheros ${BUILD}/initrd/init
|
||||||
|
cp scripts/dockerimages/scripts/os-dockerfile ${BUILD}/initrd/Dockerfile
|
||||||
|
|
||||||
|
cd ${BUILD}/initrd
|
||||||
|
|
||||||
|
find | cpio -H newc -o | lzma -c > ${DIST}/artifacts/initrd
|
||||||
|
|
||||||
|
CD=${BUILD}/cd
|
||||||
|
|
||||||
|
mkdir -p ${CD}/boot/isolinux
|
||||||
|
cp ${DIST}/artifacts/vmlinuz ${CD}/boot
|
||||||
|
cp ${DIST}/artifacts/initrd ${CD}/boot
|
||||||
|
cp /usr/lib/syslinux/isolinux.bin ${CD}/boot/isolinux
|
||||||
|
cp /usr/lib/syslinux/linux.c32 ${CD}/boot/isolinux/ldlinux.c32
|
||||||
|
cat > ${CD}/boot/isolinux/isolinux.cfg << EOF
|
||||||
|
default rancheros
|
||||||
|
label rancheros
|
||||||
|
kernel /boot/vmlinuz
|
||||||
|
initrd /boot/initrd
|
||||||
|
append quiet
|
||||||
|
|
||||||
|
prompt 1
|
||||||
|
timeout 1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Copied from boot2docker, thanks.
|
||||||
|
cd ${CD}
|
||||||
|
xorriso \
|
||||||
|
-publisher "Rancher Labs, Inc." \
|
||||||
|
-as mkisofs \
|
||||||
|
-l -J -R -V "RancherOS" \
|
||||||
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
||||||
|
-b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
|
||||||
|
-isohybrid-mbr /usr/lib/syslinux/isohdpfx.bin \
|
||||||
|
-o ${DIST}/artifacts/rancheros.iso $(pwd)
|
45
scripts/run
Executable file
45
scripts/run
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
source scripts/build-common
|
||||||
|
|
||||||
|
BASE=$(pwd)
|
||||||
|
|
||||||
|
KERNEL=${BASE}/dist/artifacts/vmlinuz
|
||||||
|
INITRD=${BASE}/dist/artifacts/initrd
|
||||||
|
HD=${BASE}/build/empty-hd.img
|
||||||
|
HD_GZ=${ARTIFACTS}/empty-hd.img.gz
|
||||||
|
INITRD_TMP=${BUILD}/$(sha1sum ${INITRD} | awk '{print $1}')
|
||||||
|
INITRD_TEST=${BUILD}/initrd.test
|
||||||
|
|
||||||
|
if [[ ! -e ${KERNEL} || ! -e ${INITRD} ]]; then
|
||||||
|
echo "Failed to find ${KERNEL} or ${INITRD}" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d ${INITRD_TMP} ]; then
|
||||||
|
mkdir -p ${INITRD_TMP}
|
||||||
|
pushd ${INITRD_TMP}
|
||||||
|
lzma -dc ${INITRD} | sudo cpio -idmv
|
||||||
|
rm -f init
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp bin/rancheros ${INITRD_TMP}/init
|
||||||
|
cd ${INITRD_TMP}
|
||||||
|
|
||||||
|
if [ "$1" == "--docker" ]; then
|
||||||
|
docker build -t rancheros-run .
|
||||||
|
docker run --privileged -it rancheros-run
|
||||||
|
else
|
||||||
|
find | cpio -H newc -o > ${INITRD_TEST}
|
||||||
|
|
||||||
|
if [ ! -e ${HD} ]; then
|
||||||
|
zcat ${HD_GZ} > ${HD}
|
||||||
|
fi
|
||||||
|
|
||||||
|
kvm -m 1024 -kernel ${KERNEL} -initrd ${INITRD_TEST} -append "$1" -hda ${HD} -serial stdio -netdev user,id=hostnet0 -device virtio-net-pci,romfile=,netdev=hostnet0
|
||||||
|
fi
|
159
sysinit/sysinit.go
Normal file
159
sysinit/sysinit.go
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package sysinit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
dockerClient "github.com/fsouza/go-dockerclient"
|
||||||
|
"github.com/rancherio/os/config"
|
||||||
|
"github.com/rancherio/os/docker"
|
||||||
|
initPkg "github.com/rancherio/os/init"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SysInit() {
|
||||||
|
if err := sysInit(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func importImage(client *dockerClient.Client, name, fileName string) error {
|
||||||
|
file, err := os.Open(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
log.Debugf("Importing image for %s", fileName)
|
||||||
|
repo, tag := dockerClient.ParseRepositoryTag(name)
|
||||||
|
return client.ImportImage(dockerClient.ImportImageOptions{
|
||||||
|
Source: "-",
|
||||||
|
Repository: repo,
|
||||||
|
Tag: tag,
|
||||||
|
InputStream: file,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasImage(name string) bool {
|
||||||
|
stamp := path.Join(initPkg.STATE, name)
|
||||||
|
if _, err := os.Stat(stamp); os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func findImages(cfg *config.Config) ([]string, error) {
|
||||||
|
log.Debugf("Looking for images at %s", cfg.ImagesPath)
|
||||||
|
|
||||||
|
result := []string{}
|
||||||
|
|
||||||
|
dir, err := os.Open(cfg.ImagesPath)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
log.Debugf("Not loading images, %s does not exist")
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer dir.Close()
|
||||||
|
|
||||||
|
files, err := dir.Readdirnames(0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fileName := range files {
|
||||||
|
log.Debugf("Checking %s", fileName)
|
||||||
|
if ok, _ := path.Match(cfg.ImagesPattern, fileName); ok {
|
||||||
|
log.Debugf("Found %s", fileName)
|
||||||
|
result = append(result, fileName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadImages(cfg *config.Config) error {
|
||||||
|
images, err := findImages(cfg)
|
||||||
|
if err != nil || len(images) == 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := docker.NewClient(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, image := range images {
|
||||||
|
if hasImage(image) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
inputFileName := path.Join(cfg.ImagesPath, image)
|
||||||
|
input, err := os.Open(inputFileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer input.Close()
|
||||||
|
|
||||||
|
log.Debugf("Loading images from %s", inputFileName)
|
||||||
|
err = client.LoadImage(dockerClient.LoadImageOptions{
|
||||||
|
InputStream: input,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runContainers(cfg *config.Config) error {
|
||||||
|
containers := cfg.SystemContainers
|
||||||
|
if cfg.Rescue {
|
||||||
|
log.Debug("Running rescue container")
|
||||||
|
containers = []config.ContainerConfig{cfg.RescueContainer}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, container := range containers {
|
||||||
|
args := append([]string{"run"}, container.Options...)
|
||||||
|
args = append(args, container.Image)
|
||||||
|
args = append(args, container.Args...)
|
||||||
|
|
||||||
|
cmd := exec.Command(cfg.DockerBin, args...)
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
|
||||||
|
//log.Infof("Is a tty : %v", term.IsTerminal(0))
|
||||||
|
//log.Infof("Is a tty : %v", term.IsTerminal(1))
|
||||||
|
//log.Infof("Is a tty : %v", term.IsTerminal(2))
|
||||||
|
log.Debugf("Running %s", strings.Join(args, " "))
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to run %v: %v", args, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sysInit() error {
|
||||||
|
cfg, err := config.LoadConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
initFuncs := []config.InitFunc{
|
||||||
|
loadImages,
|
||||||
|
runContainers,
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.RunInitFuncs(cfg, initFuncs)
|
||||||
|
}
|
25
user/system-docker.go
Normal file
25
user/system-docker.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SystemDocker() {
|
||||||
|
var newEnv []string
|
||||||
|
for _, env := range os.Environ() {
|
||||||
|
if !strings.HasPrefix(env, "DOCKER_HOST=") {
|
||||||
|
newEnv = append(newEnv, env)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newEnv = append(newEnv, "DOCKER_HOST=unix://var/run/system-docker.sock")
|
||||||
|
|
||||||
|
os.Args[0] = "/usr/bin/docker"
|
||||||
|
if err := syscall.Exec(os.Args[0], os.Args, newEnv); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
96
util/util.go
Normal file
96
util/util.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/mount"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mountProc() error {
|
||||||
|
if _, err := os.Stat("/proc/self/mountinfo"); os.IsNotExist(err) {
|
||||||
|
if _, err := os.Stat("/proc"); os.IsNotExist(err) {
|
||||||
|
if err = os.Mkdir("/proc", 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := syscall.Mount("none", "/proc", "proc", 0, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Mount(device, directory, fsType, options string) error {
|
||||||
|
if err := mountProc(); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(directory); os.IsNotExist(err) {
|
||||||
|
err = os.MkdirAll(directory, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mount.Mount(device, directory, fsType, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Remount(directory, options string) error {
|
||||||
|
return mount.Mount("", directory, "", fmt.Sprintf("remount,%s", options))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtractTar(archive string, dest string) error {
|
||||||
|
f, err := os.Open(archive)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
input := tar.NewReader(f)
|
||||||
|
|
||||||
|
for {
|
||||||
|
header, err := input.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if header == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInfo := header.FileInfo()
|
||||||
|
fileName := path.Join(dest, header.Name)
|
||||||
|
if fileInfo.IsDir() {
|
||||||
|
//log.Debugf("DIR : %s", fileName)
|
||||||
|
err = os.MkdirAll(fileName, fileInfo.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//log.Debugf("FILE: %s", fileName)
|
||||||
|
destFile, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fileInfo.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(destFile, input)
|
||||||
|
// Not deferring, concerned about holding open too many files
|
||||||
|
destFile.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user