package network import ( "fmt" "io/ioutil" "os" "os/signal" "path/filepath" "strconv" "syscall" "text/template" "github.com/rancher/os/config" "github.com/rancher/os/pkg/docker" "github.com/rancher/os/pkg/hostname" "github.com/rancher/os/pkg/log" "github.com/rancher/os/pkg/netconf" "github.com/docker/libnetwork/resolvconf" "golang.org/x/net/context" ) var funcMap = template.FuncMap{ "addFunc": func(a, b int) string { return strconv.Itoa(a + b) }, } func Main() { log.InitLogger() cfg := config.LoadConfig() ApplyNetworkConfig(cfg) log.Infof("Restart syslog") client, err := docker.NewSystemClient() if err != nil { log.Error(err) } if err := client.ContainerRestart(context.Background(), "syslog", 10); err != nil { log.Error(err) } signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, syscall.SIGTERM) <-signalChan log.Info("Received SIGTERM, shutting down") netconf.StopWpaSupplicant() netconf.StopDhcpcd() } func ApplyNetworkConfig(cfg *config.CloudConfig) { log.Infof("Apply Network Config") userSetDNS := len(cfg.Rancher.Network.DNS.Nameservers) > 0 || len(cfg.Rancher.Network.DNS.Search) > 0 if err := hostname.SetHostnameFromCloudConfig(cfg); err != nil { log.Errorf("Failed to set hostname from cloud config: %v", err) } userSetHostname := cfg.Hostname != "" if cfg.Rancher.Network.DHCPTimeout <= 0 { cfg.Rancher.Network.DHCPTimeout = cfg.Rancher.Defaults.Network.DHCPTimeout } // In order to handle the STATIC mode in Wi-Fi network, we have to update the dhcpcd.conf file. // https://wiki.archlinux.org/index.php/dhcpcd#Static_profile if len(cfg.Rancher.Network.WifiNetworks) > 0 { generateDhcpcdFiles(cfg) generateWpaFiles(cfg) } dhcpSetDNS, err := netconf.ApplyNetworkConfigs(&cfg.Rancher.Network, userSetHostname, userSetDNS) if err != nil { log.Errorf("Failed to apply network configs(by netconf): %v", err) } if dhcpSetDNS { log.Infof("DNS set by DHCP") } if !userSetDNS && !dhcpSetDNS { // only write 8.8.8.8,8.8.4.4 as a last resort log.Infof("Writing default resolv.conf - no user setting, and no DHCP setting") if _, err := resolvconf.Build("/etc/resolv.conf", cfg.Rancher.Defaults.Network.DNS.Nameservers, cfg.Rancher.Defaults.Network.DNS.Search, nil); err != nil { log.Errorf("Failed to write resolv.conf (!userSetDNS and !dhcpSetDNS): %v", err) } } if userSetDNS { if _, err := resolvconf.Build("/etc/resolv.conf", cfg.Rancher.Network.DNS.Nameservers, cfg.Rancher.Network.DNS.Search, nil); err != nil { log.Errorf("Failed to write resolv.conf (userSetDNS): %v", err) } else { log.Infof("writing to /etc/resolv.conf: nameservers: %v, search: %v", cfg.Rancher.Network.DNS.Nameservers, cfg.Rancher.Network.DNS.Search) } } resolve, err := ioutil.ReadFile("/etc/resolv.conf") log.Debugf("Resolve.conf == [%s], %v", resolve, err) log.Infof("Apply Network Config SyncHostname") if err := hostname.SyncHostname(); err != nil { log.Errorf("Failed to sync hostname: %v", err) } } func generateDhcpcdFiles(cfg *config.CloudConfig) { networks := cfg.Rancher.Network.WifiNetworks interfaces := cfg.Rancher.Network.Interfaces configs := make(map[string]netconf.WifiNetworkConfig) for k, v := range interfaces { if c, ok := networks[v.WifiNetwork]; ok && c.Address != "" { configs[k] = c } } f, err := os.Create(config.DHCPCDConfigFile) defer f.Close() if err != nil { log.Errorf("Failed to open file: %s err: %v", config.DHCPCDConfigFile, err) } templateFiles := []string{config.DHCPCDTemplateFile} templateName := filepath.Base(templateFiles[0]) p := template.Must(template.New(templateName).ParseFiles(templateFiles...)) if err = p.Execute(f, configs); err != nil { log.Errorf("Failed to wrote wpa configuration to %s: %v", config.DHCPCDConfigFile, err) } } func generateWpaFiles(cfg *config.CloudConfig) { networks := cfg.Rancher.Network.WifiNetworks interfaces := cfg.Rancher.Network.Interfaces for k, v := range interfaces { if v.WifiNetwork != "" { configs := make(map[string]netconf.WifiNetworkConfig) filename := fmt.Sprintf(config.WPAConfigFile, k) f, err := os.Create(filename) if err != nil { log.Errorf("Failed to open file: %s err: %v", filename, err) } if c, ok := networks[v.WifiNetwork]; ok { configs[v.WifiNetwork] = c } templateFiles := []string{config.WPATemplateFile} templateName := filepath.Base(templateFiles[0]) p := template.Must(template.New(templateName).Funcs(funcMap).ParseFiles(templateFiles...)) if err = p.Execute(f, configs); err != nil { log.Errorf("Failed to wrote wpa configuration to %s: %v", filename, err) } f.Close() } } }