network.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package network
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "os/signal"
  7. "path/filepath"
  8. "strconv"
  9. "syscall"
  10. "text/template"
  11. "github.com/rancher/os/config"
  12. "github.com/rancher/os/pkg/docker"
  13. "github.com/rancher/os/pkg/hostname"
  14. "github.com/rancher/os/pkg/log"
  15. "github.com/rancher/os/pkg/netconf"
  16. "github.com/docker/libnetwork/resolvconf"
  17. "golang.org/x/net/context"
  18. )
  19. var funcMap = template.FuncMap{
  20. "addFunc": func(a, b int) string {
  21. return strconv.Itoa(a + b)
  22. },
  23. }
  24. func Main() {
  25. log.InitLogger()
  26. cfg := config.LoadConfig()
  27. ApplyNetworkConfig(cfg)
  28. log.Infof("Restart syslog")
  29. client, err := docker.NewSystemClient()
  30. if err != nil {
  31. log.Error(err)
  32. }
  33. if err := client.ContainerRestart(context.Background(), "syslog", 10); err != nil {
  34. log.Error(err)
  35. }
  36. signalChan := make(chan os.Signal, 1)
  37. signal.Notify(signalChan, syscall.SIGTERM)
  38. <-signalChan
  39. log.Info("Received SIGTERM, shutting down")
  40. netconf.StopWpaSupplicant()
  41. netconf.StopDhcpcd()
  42. }
  43. func ApplyNetworkConfig(cfg *config.CloudConfig) {
  44. log.Infof("Apply Network Config")
  45. userSetDNS := len(cfg.Rancher.Network.DNS.Nameservers) > 0 || len(cfg.Rancher.Network.DNS.Search) > 0
  46. if err := hostname.SetHostnameFromCloudConfig(cfg); err != nil {
  47. log.Errorf("Failed to set hostname from cloud config: %v", err)
  48. }
  49. userSetHostname := cfg.Hostname != ""
  50. if cfg.Rancher.Network.DHCPTimeout <= 0 {
  51. cfg.Rancher.Network.DHCPTimeout = cfg.Rancher.Defaults.Network.DHCPTimeout
  52. }
  53. // In order to handle the STATIC mode in Wi-Fi network, we have to update the dhcpcd.conf file.
  54. // https://wiki.archlinux.org/index.php/dhcpcd#Static_profile
  55. if len(cfg.Rancher.Network.WifiNetworks) > 0 {
  56. generateDhcpcdFiles(cfg)
  57. generateWpaFiles(cfg)
  58. }
  59. dhcpSetDNS, err := netconf.ApplyNetworkConfigs(&cfg.Rancher.Network, userSetHostname, userSetDNS)
  60. if err != nil {
  61. log.Errorf("Failed to apply network configs(by netconf): %v", err)
  62. }
  63. if dhcpSetDNS {
  64. log.Infof("DNS set by DHCP")
  65. }
  66. if !userSetDNS && !dhcpSetDNS {
  67. // only write 8.8.8.8,8.8.4.4 as a last resort
  68. log.Infof("Writing default resolv.conf - no user setting, and no DHCP setting")
  69. if _, err := resolvconf.Build("/etc/resolv.conf",
  70. cfg.Rancher.Defaults.Network.DNS.Nameservers,
  71. cfg.Rancher.Defaults.Network.DNS.Search,
  72. nil); err != nil {
  73. log.Errorf("Failed to write resolv.conf (!userSetDNS and !dhcpSetDNS): %v", err)
  74. }
  75. }
  76. if userSetDNS {
  77. if _, err := resolvconf.Build("/etc/resolv.conf", cfg.Rancher.Network.DNS.Nameservers, cfg.Rancher.Network.DNS.Search, nil); err != nil {
  78. log.Errorf("Failed to write resolv.conf (userSetDNS): %v", err)
  79. } else {
  80. log.Infof("writing to /etc/resolv.conf: nameservers: %v, search: %v", cfg.Rancher.Network.DNS.Nameservers, cfg.Rancher.Network.DNS.Search)
  81. }
  82. }
  83. resolve, err := ioutil.ReadFile("/etc/resolv.conf")
  84. log.Debugf("Resolve.conf == [%s], %v", resolve, err)
  85. log.Infof("Apply Network Config SyncHostname")
  86. if err := hostname.SyncHostname(); err != nil {
  87. log.Errorf("Failed to sync hostname: %v", err)
  88. }
  89. }
  90. func generateDhcpcdFiles(cfg *config.CloudConfig) {
  91. networks := cfg.Rancher.Network.WifiNetworks
  92. interfaces := cfg.Rancher.Network.Interfaces
  93. configs := make(map[string]netconf.WifiNetworkConfig)
  94. for k, v := range interfaces {
  95. if c, ok := networks[v.WifiNetwork]; ok && c.Address != "" {
  96. configs[k] = c
  97. }
  98. }
  99. f, err := os.Create(config.DHCPCDConfigFile)
  100. defer f.Close()
  101. if err != nil {
  102. log.Errorf("Failed to open file: %s err: %v", config.DHCPCDConfigFile, err)
  103. }
  104. templateFiles := []string{config.DHCPCDTemplateFile}
  105. templateName := filepath.Base(templateFiles[0])
  106. p := template.Must(template.New(templateName).ParseFiles(templateFiles...))
  107. if err = p.Execute(f, configs); err != nil {
  108. log.Errorf("Failed to wrote wpa configuration to %s: %v", config.DHCPCDConfigFile, err)
  109. }
  110. }
  111. func generateWpaFiles(cfg *config.CloudConfig) {
  112. networks := cfg.Rancher.Network.WifiNetworks
  113. interfaces := cfg.Rancher.Network.Interfaces
  114. for k, v := range interfaces {
  115. if v.WifiNetwork != "" {
  116. configs := make(map[string]netconf.WifiNetworkConfig)
  117. filename := fmt.Sprintf(config.WPAConfigFile, k)
  118. f, err := os.Create(filename)
  119. if err != nil {
  120. log.Errorf("Failed to open file: %s err: %v", filename, err)
  121. }
  122. if c, ok := networks[v.WifiNetwork]; ok {
  123. configs[v.WifiNetwork] = c
  124. }
  125. templateFiles := []string{config.WPATemplateFile}
  126. templateName := filepath.Base(templateFiles[0])
  127. p := template.Must(template.New(templateName).Funcs(funcMap).ParseFiles(templateFiles...))
  128. if err = p.Execute(f, configs); err != nil {
  129. log.Errorf("Failed to wrote wpa configuration to %s: %v", filename, err)
  130. }
  131. f.Close()
  132. }
  133. }
  134. }