mirror of
https://github.com/rancher/os.git
synced 2025-08-29 19:44:22 +00:00
Add ipxe support
This commit is contained in:
parent
b4cc0014b2
commit
0e46d19194
@ -4,7 +4,7 @@ RUN zypper ref
|
|||||||
ARG DAPPER_HOST_ARCH
|
ARG DAPPER_HOST_ARCH
|
||||||
ENV ARCH $DAPPER_HOST_ARCH
|
ENV ARCH $DAPPER_HOST_ARCH
|
||||||
|
|
||||||
RUN zypper in -y bash git gcc docker vim less file curl wget ca-certificates make mkisofs go1.16
|
RUN zypper in -y bash git gcc docker vim less file curl wget ca-certificates make mkisofs go1.16 qemu-tools
|
||||||
RUN go get golang.org/x/tools/cmd/goimports
|
RUN go get golang.org/x/tools/cmd/goimports
|
||||||
RUN if [ "${ARCH}" == "amd64" ]; then \
|
RUN if [ "${ARCH}" == "amd64" ]; then \
|
||||||
curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.40.1; \
|
curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.40.1; \
|
||||||
|
4
Makefile
4
Makefile
@ -68,6 +68,10 @@ ami:
|
|||||||
run:
|
run:
|
||||||
./scripts/run
|
./scripts/run
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
pxe:
|
||||||
|
./scripts/run pxe
|
||||||
|
|
||||||
all-amis: \
|
all-amis: \
|
||||||
ami-us-west-1 \
|
ami-us-west-1 \
|
||||||
ami-us-west-2
|
ami-us-west-2
|
||||||
|
@ -2,18 +2,36 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/rancher/os/pkg/config"
|
||||||
"github.com/rancher/os/pkg/install"
|
"github.com/rancher/os/pkg/install"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
output = flag.Bool("automatic", false, "Check for and run automatic installation")
|
output = flag.Bool("automatic", false, "Check for and run automatic installation")
|
||||||
|
printConfig = flag.Bool("print-config", false, "Print effective configuration and exit")
|
||||||
|
configFile = flag.String("config-file", "", "Config file to use, local file or http/tftp URL")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if err := install.Run(*output); err != nil {
|
if *printConfig {
|
||||||
|
cfg, err := config.ReadConfig(*configFile)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
data, err := yaml.Marshal(cfg)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
os.Stdout.Write(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := install.Run(*output, *configFile); err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
/usr/lib/systemd/system/ros-installer.service
|
17
framework/files/usr/lib/systemd/system/ros-installer.service
Normal file
17
framework/files/usr/lib/systemd/system/ros-installer.service
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=RancherOS Automatic Installation
|
||||||
|
Documentation=https://github.com/rancher/os
|
||||||
|
Wants=network-online.target
|
||||||
|
After=network-online.target
|
||||||
|
Before=getty-pre.target serial-getty@ttyS0.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
EnvironmentFile=-/etc/default/%N
|
||||||
|
EnvironmentFile=-/etc/sysconfig/%N
|
||||||
|
TimeoutStartSec=0
|
||||||
|
StandardOutput=journal+console
|
||||||
|
ExecStart=/usr/sbin/ros-installer -automatic
|
3
go.mod
3
go.mod
@ -4,12 +4,13 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/mattn/go-isatty v0.0.10
|
github.com/mattn/go-isatty v0.0.10
|
||||||
|
github.com/pin/tftp v2.1.0+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/rancher/wrangler v0.8.3
|
github.com/rancher/wrangler v0.8.3
|
||||||
github.com/sirupsen/logrus v1.4.2
|
github.com/sirupsen/logrus v1.4.2
|
||||||
github.com/stretchr/testify v1.4.0
|
|
||||||
github.com/tredoe/osutil v1.0.5
|
github.com/tredoe/osutil v1.0.5
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||||
|
gopkg.in/pin/tftp.v2 v2.1.0
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
4
go.sum
4
go.sum
@ -244,6 +244,8 @@ github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu
|
|||||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
|
github.com/pin/tftp v2.1.0+incompatible h1:Yng4J7jv6lOc6IF4XoB5mnd3P7ZrF60XQq+my3FAMus=
|
||||||
|
github.com/pin/tftp v2.1.0+incompatible/go.mod h1:xVpZOMCXTy+A5QMjEVN0Glwa1sUvaJhFXbr/aAxuxGY=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
@ -473,6 +475,8 @@ gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
|||||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
|
gopkg.in/pin/tftp.v2 v2.1.0 h1:QbLeBeg/UoYf1dkjJS5nLj/x9t8gFQRG06fq5PEOWDw=
|
||||||
|
gopkg.in/pin/tftp.v2 v2.1.0/go.mod h1:OptUw+bblWIH7jYabWNBP0CAH4/sBtD2N0oBeXcRG98=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
type Rancher struct {
|
type RancherOS struct {
|
||||||
Install Install `json:"install,omitempty"`
|
Install Install `json:"install,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,31 +15,22 @@ type Install struct {
|
|||||||
NoFormat bool `json:"noFormat,omitempty"`
|
NoFormat bool `json:"noFormat,omitempty"`
|
||||||
Debug bool `json:"debug,omitempty"`
|
Debug bool `json:"debug,omitempty"`
|
||||||
TTY string `json:"tty,omitempty"`
|
TTY string `json:"tty,omitempty"`
|
||||||
ServerURL string `json:"serverUrl,omitempty"`
|
|
||||||
Token string `json:"token,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
SSHAuthorizedKeys []string `json:"sshAuthorizedKeys,omitempty"`
|
SSHAuthorizedKeys []string `json:"sshAuthorizedKeys,omitempty"`
|
||||||
Rancher Rancher `json:"rancher,omitempty"`
|
RancherOS RancherOS `json:"rancheros,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type YipConfig struct {
|
type YipConfig struct {
|
||||||
Stages map[string][]Stage `json:"stages,omitempty"`
|
Stages map[string][]Stage `json:"stages,omitempty"`
|
||||||
Rancherd Rancherd `json:"rancherd,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Stage struct {
|
type Stage struct {
|
||||||
Users map[string]User `json:"users,omitempty"`
|
Users map[string]User `json:"users,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rancherd struct {
|
|
||||||
Server string `json:"server,omitempty"`
|
|
||||||
Role string `json:"role,omitempty"`
|
|
||||||
Token string `json:"token,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
PasswordHash string `json:"passwd,omitempty"`
|
PasswordHash string `json:"passwd,omitempty"`
|
||||||
|
@ -3,6 +3,7 @@ package config
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@ -10,18 +11,20 @@ import (
|
|||||||
values "github.com/rancher/wrangler/pkg/data"
|
values "github.com/rancher/wrangler/pkg/data"
|
||||||
"github.com/rancher/wrangler/pkg/data/convert"
|
"github.com/rancher/wrangler/pkg/data/convert"
|
||||||
schemas2 "github.com/rancher/wrangler/pkg/schemas"
|
schemas2 "github.com/rancher/wrangler/pkg/schemas"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
defaultMappers = schemas2.Mappers{
|
||||||
|
NewToMap(),
|
||||||
|
NewToSlice(),
|
||||||
|
NewToBool(),
|
||||||
|
&FuzzyNames{},
|
||||||
|
}
|
||||||
schemas = schemas2.EmptySchemas().Init(func(s *schemas2.Schemas) *schemas2.Schemas {
|
schemas = schemas2.EmptySchemas().Init(func(s *schemas2.Schemas) *schemas2.Schemas {
|
||||||
s.DefaultMapper = func() schemas2.Mapper {
|
s.AddMapper("config", defaultMappers)
|
||||||
return schemas2.Mappers{
|
s.AddMapper("rancherOS", defaultMappers)
|
||||||
NewToMap(),
|
s.AddMapper("install", defaultMappers)
|
||||||
NewToSlice(),
|
|
||||||
NewToBool(),
|
|
||||||
&FuzzyNames{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
return s
|
||||||
}).MustImport(Config{})
|
}).MustImport(Config{})
|
||||||
schema = schemas.Schema("config")
|
schema = schemas.Schema("config")
|
||||||
@ -40,7 +43,7 @@ func mapToEnv(prefix string, data map[string]interface{}) []string {
|
|||||||
var result []string
|
var result []string
|
||||||
for k, v := range data {
|
for k, v := range data {
|
||||||
keyName := strings.ToUpper(prefix + convert.ToYAMLKey(k))
|
keyName := strings.ToUpper(prefix + convert.ToYAMLKey(k))
|
||||||
keyName = strings.ReplaceAll(keyName, "RANCHER_", "COS_")
|
keyName = strings.ReplaceAll(keyName, "RANCHEROS_", "COS_")
|
||||||
if data, ok := v.(map[string]interface{}); ok {
|
if data, ok := v.(map[string]interface{}); ok {
|
||||||
subResult := mapToEnv(keyName+"_", data)
|
subResult := mapToEnv(keyName+"_", data)
|
||||||
result = append(result, subResult...)
|
result = append(result, subResult...)
|
||||||
@ -51,14 +54,86 @@ func mapToEnv(prefix string, data map[string]interface{}) []string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadConfig() (Config, error) {
|
func readFile(path string) (result map[string]interface{}, _ error) {
|
||||||
result := Config{}
|
result = map[string]interface{}{}
|
||||||
|
defer func() {
|
||||||
|
if v, ok := result["install"]; ok {
|
||||||
|
values.PutValue(result, v, "rancheros", "install")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
data, err := readCmdline()
|
switch {
|
||||||
if err != nil {
|
case strings.HasPrefix(path, "http://"):
|
||||||
return result, err
|
fallthrough
|
||||||
|
case strings.HasPrefix(path, "https://"):
|
||||||
|
resp, err := http.Get(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
buffer, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read %s: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, yaml.Unmarshal(buffer, &result)
|
||||||
|
case strings.HasPrefix(path, "tftp://"):
|
||||||
|
return tftpGet(path)
|
||||||
}
|
}
|
||||||
if err := schema.Mapper.ToInternal(data); err != nil {
|
|
||||||
|
f, err := ioutil.ReadFile(path)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := map[string]interface{}{}
|
||||||
|
if err := yaml.Unmarshal(f, &data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type reader func() (map[string]interface{}, error)
|
||||||
|
|
||||||
|
func merge(readers ...reader) (map[string]interface{}, error) {
|
||||||
|
d := map[string]interface{}{}
|
||||||
|
for _, r := range readers {
|
||||||
|
newData, err := r()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := schema.Mapper.ToInternal(newData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
d = values.MergeMapsConcatSlice(d, newData)
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readConfigMap(cfg string) (map[string]interface{}, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
data map[string]interface{}
|
||||||
|
)
|
||||||
|
return merge(func() (map[string]interface{}, error) {
|
||||||
|
data, err = merge(readCmdline,
|
||||||
|
func() (map[string]interface{}, error) {
|
||||||
|
return readFile(cfg)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return data, err
|
||||||
|
}, func() (map[string]interface{}, error) {
|
||||||
|
return readFile(convert.ToString(values.GetValueN(data, "rancheros", "install", "configUrl")))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadConfig(cfg string) (result Config, err error) {
|
||||||
|
data, err := readConfigMap(cfg)
|
||||||
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +147,11 @@ func readCmdline() (map[string]interface{}, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, err := ioutil.ReadFile("/proc/cmdline")
|
procCmdLine := os.Getenv("PROC_CMDLINE")
|
||||||
|
if procCmdLine == "" {
|
||||||
|
procCmdLine = "/proc/cmdline"
|
||||||
|
}
|
||||||
|
bytes, err := ioutil.ReadFile(procCmdLine)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
@ -30,7 +30,9 @@ func (f *FuzzyNames) addName(name, toName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *FuzzyNames) ModifySchema(schema *schemas2.Schema, schemas *schemas2.Schemas) error {
|
func (f *FuzzyNames) ModifySchema(schema *schemas2.Schema, schemas *schemas2.Schemas) error {
|
||||||
f.names = map[string]string{}
|
if f.names == nil {
|
||||||
|
f.names = map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
for name := range schema.ResourceFields {
|
for name := range schema.ResourceFields {
|
||||||
if strings.HasSuffix(name, "s") && len(name) > 1 {
|
if strings.HasSuffix(name, "s") && len(name) > 1 {
|
||||||
|
41
pkg/config/tftpget.go
Normal file
41
pkg/config/tftpget.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"gopkg.in/pin/tftp.v2"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func tftpGet(tftpURL string) (map[string]interface{}, error) {
|
||||||
|
u, err := url.Parse(tftpURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
host, _, err := net.SplitHostPort(u.Host)
|
||||||
|
if err != nil {
|
||||||
|
host = u.Host + ":69"
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Downloading config from host %s, file %s\n", host, u.Path)
|
||||||
|
client, err := tftp.NewClient(host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
writerTo, err := client.Receive(u.Path, "octet")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
if _, err := writerTo.WriteTo(buf); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]interface{}{}
|
||||||
|
return result, yaml.Unmarshal(buf.Bytes(), &result)
|
||||||
|
}
|
@ -6,10 +6,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func PrintInstall(cfg Config) ([]byte, error) {
|
func PrintInstall(cfg Config) ([]byte, error) {
|
||||||
if cfg.Rancher.Install.Password != "" {
|
if cfg.RancherOS.Install.Password != "" {
|
||||||
cfg.Rancher.Install.Password = "******"
|
cfg.RancherOS.Install.Password = "******"
|
||||||
}
|
}
|
||||||
data, err := convert.EncodeToMap(cfg.Rancher.Install)
|
data, err := convert.EncodeToMap(cfg.RancherOS.Install)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Ask(cfg *config.Config) error {
|
func Ask(cfg *config.Config) error {
|
||||||
if cfg.Rancher.Install.Silent {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := AskInstallDevice(cfg); err != nil {
|
if err := AskInstallDevice(cfg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -22,7 +18,7 @@ func Ask(cfg *config.Config) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Rancher.Install.ConfigURL == "" {
|
if cfg.RancherOS.Install.ConfigURL == "" {
|
||||||
if err := AskGithub(cfg); err != nil {
|
if err := AskGithub(cfg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -30,17 +26,13 @@ func Ask(cfg *config.Config) error {
|
|||||||
if err := AskPassword(cfg); err != nil {
|
if err := AskPassword(cfg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := AskServerAgent(cfg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AskInstallDevice(cfg *config.Config) error {
|
func AskInstallDevice(cfg *config.Config) error {
|
||||||
if cfg.Rancher.Install.Device != "" {
|
if cfg.RancherOS.Install.Device != "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,69 +46,22 @@ func AskInstallDevice(cfg *config.Config) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Rancher.Install.Device = "/dev/" + fields[i]
|
cfg.RancherOS.Install.Device = "/dev/" + fields[i]
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AskToken(cfg *config.Config, server bool) error {
|
func isServer(cfg *config.Config) (bool, bool, error) {
|
||||||
var (
|
opts := []string{"server", "agent", "none"}
|
||||||
token string
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
if cfg.Rancher.Install.Token != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := "Token or cluster secret"
|
|
||||||
if server {
|
|
||||||
msg += " (optional)"
|
|
||||||
}
|
|
||||||
if server {
|
|
||||||
token, err = questions.PromptOptional(msg+": ", "")
|
|
||||||
} else {
|
|
||||||
token, err = questions.Prompt(msg+": ", "")
|
|
||||||
}
|
|
||||||
cfg.Rancher.Install.Token = token
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func isServer(cfg *config.Config) (bool, error) {
|
|
||||||
opts := []string{"server", "agent"}
|
|
||||||
i, err := questions.PromptFormattedOptions("Run as server or agent?", 0, opts...)
|
i, err := questions.PromptFormattedOptions("Run as server or agent?", 0, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return i == 0, nil
|
return i == 0, i == 1, nil
|
||||||
}
|
|
||||||
|
|
||||||
func AskServerAgent(cfg *config.Config) error {
|
|
||||||
if cfg.Rancher.Install.ServerURL != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
server, err := isServer(cfg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if server {
|
|
||||||
return AskToken(cfg, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
url, err := questions.Prompt("URL of server: ", "")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cfg.Rancher.Install.ServerURL = url
|
|
||||||
|
|
||||||
return AskToken(cfg, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func AskPassword(cfg *config.Config) error {
|
func AskPassword(cfg *config.Config) error {
|
||||||
if cfg.Rancher.Install.Silent || cfg.Rancher.Install.Password != "" {
|
if cfg.RancherOS.Install.Silent || cfg.RancherOS.Install.Password != "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,12 +85,12 @@ func AskPassword(cfg *config.Config) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Rancher.Install.Password = pass
|
cfg.RancherOS.Install.Password = pass
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AskGithub(cfg *config.Config) error {
|
func AskGithub(cfg *config.Config) error {
|
||||||
if len(cfg.SSHAuthorizedKeys) > 0 || cfg.Rancher.Install.Password != "" {
|
if len(cfg.SSHAuthorizedKeys) > 0 || cfg.RancherOS.Install.Password != "" || cfg.RancherOS.Install.Silent {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +112,7 @@ func AskGithub(cfg *config.Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AskConfigURL(cfg *config.Config) error {
|
func AskConfigURL(cfg *config.Config) error {
|
||||||
if cfg.Rancher.Install.ConfigURL != "" {
|
if cfg.RancherOS.Install.ConfigURL != "" || cfg.RancherOS.Install.Silent {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +130,6 @@ func AskConfigURL(cfg *config.Config) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Rancher.Install.ConfigURL = str
|
cfg.RancherOS.Install.ConfigURL = str
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package install
|
package install
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -10,16 +11,16 @@ import (
|
|||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(automatic bool) error {
|
func Run(automatic bool, configFile string) error {
|
||||||
cfg, err := config.ReadConfig()
|
cfg, err := config.ReadConfig(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if automatic && !cfg.Rancher.Install.Automatic {
|
if automatic && !cfg.RancherOS.Install.Automatic {
|
||||||
return nil
|
return nil
|
||||||
} else if automatic {
|
} else if automatic {
|
||||||
cfg.Rancher.Install.Silent = true
|
cfg.RancherOS.Install.Silent = true
|
||||||
}
|
}
|
||||||
|
|
||||||
err = Ask(&cfg)
|
err = Ask(&cfg)
|
||||||
@ -44,7 +45,7 @@ func runInstall(cfg config.Config, output string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cfg.Rancher.Install.Silent {
|
if !cfg.RancherOS.Install.Silent {
|
||||||
val, err := questions.PromptBool("\nConfiguration\n"+"-------------\n\n"+
|
val, err := questions.PromptBool("\nConfiguration\n"+"-------------\n\n"+
|
||||||
string(installBytes)+
|
string(installBytes)+
|
||||||
"\nYour disk will be formatted and installed with the above configuration.\nContinue?", false)
|
"\nYour disk will be formatted and installed with the above configuration.\nContinue?", false)
|
||||||
@ -53,30 +54,20 @@ func runInstall(cfg config.Config, output string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Rancher.Install.ConfigURL == "" {
|
if cfg.RancherOS.Install.ConfigURL == "" && !cfg.RancherOS.Install.Silent {
|
||||||
yip := config.YipConfig{
|
yip := config.YipConfig{}
|
||||||
Rancherd: config.Rancherd{
|
if cfg.RancherOS.Install.Password != "" || len(cfg.SSHAuthorizedKeys) > 0 {
|
||||||
Server: cfg.Rancher.Install.ServerURL,
|
|
||||||
Token: cfg.Rancher.Install.Token,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if cfg.Rancher.Install.ServerURL == "" {
|
|
||||||
yip.Rancherd.Role = "cluster-init"
|
|
||||||
} else {
|
|
||||||
yip.Rancherd.Role = "agent"
|
|
||||||
}
|
|
||||||
if cfg.Rancher.Install.Password != "" || len(cfg.SSHAuthorizedKeys) > 0 {
|
|
||||||
yip.Stages = map[string][]config.Stage{
|
yip.Stages = map[string][]config.Stage{
|
||||||
"network": {{
|
"network": {{
|
||||||
Users: map[string]config.User{
|
Users: map[string]config.User{
|
||||||
"root": {
|
"root": {
|
||||||
Name: "root",
|
Name: "root",
|
||||||
PasswordHash: cfg.Rancher.Install.Password,
|
PasswordHash: cfg.RancherOS.Install.Password,
|
||||||
SSHAuthorizedKeys: cfg.SSHAuthorizedKeys,
|
SSHAuthorizedKeys: cfg.SSHAuthorizedKeys,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}}
|
}}
|
||||||
cfg.Rancher.Install.Password = ""
|
cfg.RancherOS.Install.Password = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := yaml.Marshal(yip)
|
data, err := yaml.Marshal(yip)
|
||||||
@ -87,7 +78,7 @@ func runInstall(cfg config.Config, output string) error {
|
|||||||
if err := ioutil.WriteFile(output+".yip", data, 0600); err != nil {
|
if err := ioutil.WriteFile(output+".yip", data, 0600); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cfg.Rancher.Install.ConfigURL = output + ".yip"
|
cfg.RancherOS.Install.ConfigURL = output + ".yip"
|
||||||
}
|
}
|
||||||
|
|
||||||
ev, err := config.ToEnv(cfg)
|
ev, err := config.ToEnv(cfg)
|
||||||
@ -95,6 +86,8 @@ func runInstall(cfg config.Config, output string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printEnv(cfg)
|
||||||
|
|
||||||
cmd := exec.Command("cos-installer")
|
cmd := exec.Command("cos-installer")
|
||||||
cmd.Env = append(os.Environ(), ev...)
|
cmd.Env = append(os.Environ(), ev...)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
@ -102,3 +95,19 @@ func runInstall(cfg config.Config, output string) error {
|
|||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printEnv(cfg config.Config) {
|
||||||
|
if cfg.RancherOS.Install.Password != "" {
|
||||||
|
cfg.RancherOS.Install.Password = "<removed>"
|
||||||
|
}
|
||||||
|
|
||||||
|
ev2, err := config.ToEnv(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Install environment:")
|
||||||
|
for _, ev := range ev2 {
|
||||||
|
fmt.Println(ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -32,6 +32,30 @@ isoinfo -x /rootfs.squashfs -R -i build/output.iso > build/output.squashfs
|
|||||||
isoinfo -x /boot/kernel.xz -R -i build/output.iso > build/output-kernel
|
isoinfo -x /boot/kernel.xz -R -i build/output.iso > build/output-kernel
|
||||||
isoinfo -x /boot/rootfs.xz -R -i build/output.iso > build/output-initrd
|
isoinfo -x /boot/rootfs.xz -R -i build/output.iso > build/output-initrd
|
||||||
|
|
||||||
|
|
||||||
|
RELEASE_URL=${RELEASE_URL:-https://github.com/rancher/os/releases/download}
|
||||||
|
INSTALL_CFG=${RELEASE_URL}/${VERSION}/example-cloud-init
|
||||||
|
PXE_ASSET_VERSION="\${version}-\${arch}"
|
||||||
|
if [ "${TAG}" = "dev" ]; then
|
||||||
|
RELEASE_URL=tftp://10.0.2.2
|
||||||
|
INSTALL_CFG=
|
||||||
|
VERSION=${TAG}
|
||||||
|
PXE_ASSET_VERSION=${TAG}
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > build/output.ipxe << EOF
|
||||||
|
#!ipxe
|
||||||
|
set arch ${ARCH}
|
||||||
|
set version ${VERSION}
|
||||||
|
set url ${RELEASE_URL}/\${version}
|
||||||
|
set kernel rancheros-${PXE_ASSET_VERSION}-kernel
|
||||||
|
set initrd rancheros-${PXE_ASSET_VERSION}-initrd
|
||||||
|
set rootfs rancheros-${PXE_ASSET_VERSION}.squashfs
|
||||||
|
kernel \${url}/\${kernel} initrd=\${initrd} ip=dhcp rd.cos.disable root=live:\${url}/\${rootfs} rancheros.install.automatic=true rancheros.install.config_url=\${config} console=tty1 console=ttyS0
|
||||||
|
initrd \${url}/\${initrd}
|
||||||
|
boot
|
||||||
|
EOF
|
||||||
|
|
||||||
mkdir -p dist/artifacts
|
mkdir -p dist/artifacts
|
||||||
for i in build/output*; do
|
for i in build/output*; do
|
||||||
mv -f $i dist/artifacts/rancheros-${TAG}${i##build/output}
|
mv -f $i dist/artifacts/rancheros-${TAG}${i##build/output}
|
||||||
|
27
scripts/run
27
scripts/run
@ -11,10 +11,34 @@ fi
|
|||||||
touch meta-data
|
touch meta-data
|
||||||
touch user-data
|
touch user-data
|
||||||
rm -f seed.iso
|
rm -f seed.iso
|
||||||
genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data
|
mkisofs -output seed.iso -volid cidata -joliet -rock user-data meta-data
|
||||||
|
BOOT=
|
||||||
|
|
||||||
|
if [ "$1" = "pxe" ]; then
|
||||||
|
shift 1
|
||||||
|
if [ ! -e ipxe.cfg ]; then
|
||||||
|
if [ ! -e ../dist/artifacts/rancheros-dev.ipxe ]; then
|
||||||
|
make -C .. package
|
||||||
|
fi
|
||||||
|
if [ -e ../dist/artifacts/rancheros-dev.ipxe ]; then
|
||||||
|
cp ../dist/artifacts/rancheros-dev.ipxe ipxe.cfg
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
BOOT="-boot cn"
|
||||||
|
|
||||||
|
if [ ! -e dev ]; then
|
||||||
|
ln -s ../dist/artifacts dev
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$1" == "" ] && [ ! -e output.iso ]; then
|
||||||
|
make -C .. build iso
|
||||||
|
fi
|
||||||
|
|
||||||
#-bios /usr/share/qemu/OVMF.fd \
|
#-bios /usr/share/qemu/OVMF.fd \
|
||||||
qemu-system-x86_64 \
|
qemu-system-x86_64 \
|
||||||
|
$BOOT \
|
||||||
-enable-kvm \
|
-enable-kvm \
|
||||||
-m ${MEMORY:=4096} \
|
-m ${MEMORY:=4096} \
|
||||||
-machine accel=${ACCEL:="kvm"} \
|
-machine accel=${ACCEL:="kvm"} \
|
||||||
@ -23,6 +47,7 @@ qemu-system-x86_64 \
|
|||||||
-serial mon:stdio \
|
-serial mon:stdio \
|
||||||
-rtc base=utc,clock=rt \
|
-rtc base=utc,clock=rt \
|
||||||
-chardev socket,path=qga.sock,server,nowait,id=qga0 \
|
-chardev socket,path=qga.sock,server,nowait,id=qga0 \
|
||||||
|
-nic user,tftp=./,bootfile=/ipxe.cfg \
|
||||||
-device virtio-serial \
|
-device virtio-serial \
|
||||||
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 \
|
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 \
|
||||||
-drive if=virtio,media=disk,file=disk.img \
|
-drive if=virtio,media=disk,file=disk.img \
|
||||||
|
Loading…
Reference in New Issue
Block a user