cloudinit.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package cloudinit
  2. import (
  3. "path/filepath"
  4. "strings"
  5. "github.com/rancher/os/config"
  6. "github.com/rancher/os/pkg/compose"
  7. "github.com/rancher/os/pkg/init/docker"
  8. "github.com/rancher/os/pkg/log"
  9. "github.com/rancher/os/pkg/sysinit"
  10. "github.com/rancher/os/pkg/util"
  11. )
  12. func CloudInit(cfg *config.CloudConfig) (*config.CloudConfig, error) {
  13. stateConfig := config.LoadConfigWithPrefix(config.StateDir)
  14. cfg.Rancher.CloudInit.Datasources = stateConfig.Rancher.CloudInit.Datasources
  15. hypervisor := util.GetHypervisor()
  16. if hypervisor == "" {
  17. log.Infof("ros init: No Detected Hypervisor")
  18. } else {
  19. log.Infof("ros init: Detected Hypervisor: %s", hypervisor)
  20. }
  21. if hypervisor == "vmware" {
  22. // add vmware to the end - we don't want to over-ride an choices the user has made
  23. cfg.Rancher.CloudInit.Datasources = append(cfg.Rancher.CloudInit.Datasources, hypervisor)
  24. }
  25. if len(cfg.Rancher.CloudInit.Datasources) == 0 {
  26. log.Info("No specific datasources, ignore cloudinit")
  27. return cfg, nil
  28. }
  29. if onlyConfigDrive(cfg.Rancher.CloudInit.Datasources) {
  30. configDev := util.ResolveDevice("LABEL=config-2")
  31. if configDev == "" {
  32. // Check v9fs: https://www.kernel.org/doc/Documentation/filesystems/9p.txt
  33. matches, _ := filepath.Glob("/sys/bus/virtio/drivers/9pnet_virtio/virtio*/mount_tag")
  34. if len(matches) == 0 {
  35. log.Info("Configdrive was enabled but has no configdrive device or filesystem, ignore cloudinit")
  36. return cfg, nil
  37. }
  38. }
  39. }
  40. if err := config.Set("rancher.cloud_init.datasources", cfg.Rancher.CloudInit.Datasources); err != nil {
  41. log.Error(err)
  42. }
  43. if stateConfig.Rancher.Network.DHCPTimeout > 0 {
  44. cfg.Rancher.Network.DHCPTimeout = stateConfig.Rancher.Network.DHCPTimeout
  45. if err := config.Set("rancher.network.dhcp_timeout", stateConfig.Rancher.Network.DHCPTimeout); err != nil {
  46. log.Error(err)
  47. }
  48. }
  49. if len(stateConfig.Rancher.Network.WifiNetworks) > 0 {
  50. cfg.Rancher.Network.WifiNetworks = stateConfig.Rancher.Network.WifiNetworks
  51. if err := config.Set("rancher.network.wifi_networks", stateConfig.Rancher.Network.WifiNetworks); err != nil {
  52. log.Error(err)
  53. }
  54. }
  55. if len(stateConfig.Rancher.Network.Interfaces) > 0 {
  56. // DO also uses static networking, but this IP may change if:
  57. // 1. not using Floating IP
  58. // 2. creating a droplet with a snapshot, the snapshot cached the previous IP
  59. if onlyDigitalOcean(cfg.Rancher.CloudInit.Datasources) {
  60. log.Info("Do not use the previous network settings on DigitalOcean")
  61. } else {
  62. cfg.Rancher.Network = stateConfig.Rancher.Network
  63. if err := config.Set("rancher.network", stateConfig.Rancher.Network); err != nil {
  64. log.Error(err)
  65. }
  66. }
  67. }
  68. log.Infof("init, runCloudInitServices(%v)", cfg.Rancher.CloudInit.Datasources)
  69. if err := runCloudInitServices(cfg); err != nil {
  70. log.Error(err)
  71. }
  72. // It'd be nice to push to rsyslog before this, but we don't have network
  73. log.AddRSyslogHook()
  74. return config.LoadConfig(), nil
  75. }
  76. func runCloudInitServices(cfg *config.CloudConfig) error {
  77. c, err := docker.Start(cfg)
  78. if err != nil {
  79. return err
  80. }
  81. defer docker.Stop(c)
  82. _, err = config.ChainCfgFuncs(cfg,
  83. []config.CfgFuncData{
  84. {"cloudinit loadImages", sysinit.LoadBootstrapImages},
  85. {"cloudinit Services", runCloudInitServiceSet},
  86. })
  87. return err
  88. }
  89. func runCloudInitServiceSet(cfg *config.CloudConfig) (*config.CloudConfig, error) {
  90. log.Info("Running cloud-init services")
  91. _, err := compose.RunServiceSet("cloud-init", cfg, cfg.Rancher.CloudInitServices)
  92. return cfg, err
  93. }
  94. func onlyConfigDrive(datasources []string) bool {
  95. if len(datasources) != 1 {
  96. return false
  97. }
  98. for _, ds := range datasources {
  99. parts := strings.SplitN(ds, ":", 2)
  100. if parts[0] == "configdrive" {
  101. return true
  102. }
  103. }
  104. return false
  105. }
  106. func onlyDigitalOcean(datasources []string) bool {
  107. if len(datasources) != 1 {
  108. return false
  109. }
  110. for _, ds := range datasources {
  111. parts := strings.SplitN(ds, ":", 2)
  112. if parts[0] == "digitalocean" {
  113. return true
  114. }
  115. }
  116. return false
  117. }