mirror of
https://github.com/rancher/os.git
synced 2025-04-28 11:24:26 +00:00
171 lines
4.7 KiB
Go
171 lines
4.7 KiB
Go
package cloudinit
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/rancher/os/config"
|
|
"github.com/rancher/os/pkg/compose"
|
|
"github.com/rancher/os/pkg/init/docker"
|
|
"github.com/rancher/os/pkg/log"
|
|
"github.com/rancher/os/pkg/sysinit"
|
|
"github.com/rancher/os/pkg/util"
|
|
)
|
|
|
|
func CloudInit(cfg *config.CloudConfig) (*config.CloudConfig, error) {
|
|
stateConfig := config.LoadConfigWithPrefix(config.StateDir)
|
|
cfg.Rancher.CloudInit.Datasources = stateConfig.Rancher.CloudInit.Datasources
|
|
|
|
hypervisor := util.GetHypervisor()
|
|
if hypervisor == "" {
|
|
log.Infof("ros init: No Detected Hypervisor")
|
|
} else {
|
|
log.Infof("ros init: Detected Hypervisor: %s", hypervisor)
|
|
}
|
|
if hypervisor == "vmware" {
|
|
// add vmware to the end - we don't want to over-ride an choices the user has made
|
|
cfg.Rancher.CloudInit.Datasources = append(cfg.Rancher.CloudInit.Datasources, hypervisor)
|
|
}
|
|
|
|
exoscale, err := onlyExoscale()
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
if exoscale {
|
|
cfg.Rancher.CloudInit.Datasources = append([]string{"exoscale"}, cfg.Rancher.CloudInit.Datasources...)
|
|
}
|
|
|
|
proxmox, err := onlyProxmox()
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
if proxmox {
|
|
cfg.Rancher.CloudInit.Datasources = append([]string{"proxmox"}, cfg.Rancher.CloutInit.Datasources...)
|
|
}
|
|
|
|
if len(cfg.Rancher.CloudInit.Datasources) == 0 {
|
|
log.Info("No specific datasources, ignore cloudinit")
|
|
return cfg, nil
|
|
}
|
|
if onlyConfigDrive(cfg.Rancher.CloudInit.Datasources) {
|
|
configDev := util.ResolveDevice("LABEL=config-2")
|
|
if configDev == "" {
|
|
// Check v9fs: https://www.kernel.org/doc/Documentation/filesystems/9p.txt
|
|
matches, _ := filepath.Glob("/sys/bus/virtio/drivers/9pnet_virtio/virtio*/mount_tag")
|
|
if len(matches) == 0 {
|
|
log.Info("Configdrive was enabled but has no configdrive device or filesystem, ignore cloudinit")
|
|
return cfg, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := config.Set("rancher.cloud_init.datasources", cfg.Rancher.CloudInit.Datasources); err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
if stateConfig.Rancher.Network.DHCPTimeout > 0 {
|
|
cfg.Rancher.Network.DHCPTimeout = stateConfig.Rancher.Network.DHCPTimeout
|
|
if err := config.Set("rancher.network.dhcp_timeout", stateConfig.Rancher.Network.DHCPTimeout); err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
|
|
if len(stateConfig.Rancher.Network.WifiNetworks) > 0 {
|
|
cfg.Rancher.Network.WifiNetworks = stateConfig.Rancher.Network.WifiNetworks
|
|
if err := config.Set("rancher.network.wifi_networks", stateConfig.Rancher.Network.WifiNetworks); err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
|
|
if len(stateConfig.Rancher.Network.Interfaces) > 0 {
|
|
// DO also uses static networking, but this IP may change if:
|
|
// 1. not using Floating IP
|
|
// 2. creating a droplet with a snapshot, the snapshot cached the previous IP
|
|
if onlyDigitalOcean(cfg.Rancher.CloudInit.Datasources) {
|
|
log.Info("Do not use the previous network settings on DigitalOcean")
|
|
} else {
|
|
cfg.Rancher.Network = stateConfig.Rancher.Network
|
|
if err := config.Set("rancher.network", stateConfig.Rancher.Network); err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
log.Infof("init, runCloudInitServices(%v)", cfg.Rancher.CloudInit.Datasources)
|
|
if err := runCloudInitServices(cfg); err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
// It'd be nice to push to rsyslog before this, but we don't have network
|
|
log.AddRSyslogHook()
|
|
|
|
return config.LoadConfig(), nil
|
|
}
|
|
|
|
func runCloudInitServices(cfg *config.CloudConfig) error {
|
|
c, err := docker.Start(cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer docker.Stop(c)
|
|
|
|
_, err = config.ChainCfgFuncs(cfg,
|
|
[]config.CfgFuncData{
|
|
{"cloudinit loadImages", sysinit.LoadBootstrapImages},
|
|
{"cloudinit Services", runCloudInitServiceSet},
|
|
})
|
|
return err
|
|
}
|
|
|
|
func runCloudInitServiceSet(cfg *config.CloudConfig) (*config.CloudConfig, error) {
|
|
log.Info("Running cloud-init services")
|
|
_, err := compose.RunServiceSet("cloud-init", cfg, cfg.Rancher.CloudInitServices)
|
|
return cfg, err
|
|
}
|
|
|
|
func onlyConfigDrive(datasources []string) bool {
|
|
if len(datasources) != 1 {
|
|
return false
|
|
}
|
|
for _, ds := range datasources {
|
|
parts := strings.SplitN(ds, ":", 2)
|
|
if parts[0] == "configdrive" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func onlyDigitalOcean(datasources []string) bool {
|
|
if len(datasources) != 1 {
|
|
return false
|
|
}
|
|
for _, ds := range datasources {
|
|
parts := strings.SplitN(ds, ":", 2)
|
|
if parts[0] == "digitalocean" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func onlyExoscale() (bool, error) {
|
|
f, err := ioutil.ReadFile("/sys/class/dmi/id/product_name")
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return strings.HasPrefix(string(f), "Exoscale"), nil
|
|
}
|
|
|
|
func onlyProxmox() (bool, error) {
|
|
f, err := ioutil.ReadFile("/sys/class/dmi/id/product_name")
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return strings.Contains(string(f), "Proxmox"), nil
|
|
}
|