func Deque(deck *deque.Deque, data ...interface{}) string { deck.CheckInvariant() if deck.Count() != len(data) { return fmt.Sprintf("Count() is %v but should be %v", deck.Count(), len(data)) } if deck.IsEmpty() != (len(data) == 0) { return fmt.Sprintf("IsEmpty() should be %v", (len(data) == 0)) } if deck.IsFull() != (len(data) == deck.Capacity()) { return fmt.Sprintf("IsFull() should be %v", (len(data) == deck.Capacity())) } for i := range data { if deck.At(i) != data[i] { return fmt.Sprintf("At(%v) is %v but should be %v", i, deck.At(i), data[i]) } if deck.Peek(i) != data[len(data)-1-i] { return fmt.Sprintf("Peek(%v) is %v but should be %v", i, deck.Peek(i), data[len(data)-1-i]) } p := deck.Put(i, "x") if p != data[i] { return fmt.Sprintf("Put(%v,x) is %v but should be %v", i, p, data[i]) } if deck.Put(i, p).(string) != "x" { return fmt.Sprintf("Put is broken") } p = deck.Poke(i, "x") if p != data[len(data)-1-i] { return fmt.Sprintf("Poke(%v,x) is %v but should be %v", i, p, data[len(data)-1-i]) } if deck.Poke(i, p).(string) != "x" { return fmt.Sprintf("Poke is broken") } if deck.At(i) != data[i] { return fmt.Sprintf("After Put/Poke At(%v) is %v but should be %v", i, deck.At(i), data[i]) } if deck.Peek(i) != data[len(data)-1-i] { return fmt.Sprintf("After Put/Poke Peek(%v) is %v but should be %v", i, deck.Peek(i), data[len(data)-1-i]) } } var zero interface{} if deck.Peek(-1) != zero { return fmt.Sprintf("Peek(-1) returns %v", deck.Peek(-1)) } if deck.Peek(-1) != nil { return fmt.Sprintf("Peek(-1) returns %v", deck.Peek(-1)) } if deck.Poke(-1, "foo") != zero { return fmt.Sprintf("Poke(-1,foo) returns not nil") } if deck.Poke(-1, "foo") != nil { return fmt.Sprintf("Poke(-1,foo) returns not nil") } if deck.At(-1) != zero { return fmt.Sprintf("At(-1) returns %v", deck.At(-1)) } if deck.At(-1) != nil { return fmt.Sprintf("At(-1) returns %v", deck.At(-1)) } if deck.Put(-1, "foo") != zero { return fmt.Sprintf("Put(-1,foo) returns not nil") } if deck.Put(-1, "foo") != nil { return fmt.Sprintf("Put(-1,foo) returns not nil") } if deck.Peek(len(data)) != zero { return fmt.Sprintf("Peek(len(data)) returns %v", deck.Peek(len(data))) } if deck.Peek(len(data)) != nil { return fmt.Sprintf("Peek(len(data)) returns %v", deck.Peek(len(data))) } if deck.Poke(len(data), "foo") != zero { return fmt.Sprintf("Poke(len(data),foo) returns not nil") } if deck.Poke(len(data), "foo") != nil { return fmt.Sprintf("Poke(len(data),foo) returns not nil") } if deck.At(len(data)) != zero { return fmt.Sprintf("At(len(data)) returns %v", deck.At(len(data))) } if deck.At(len(data)) != nil { return fmt.Sprintf("At(len(data)) returns %v", deck.At(len(data))) } if deck.Put(len(data), "foo") != zero { return fmt.Sprintf("Put(len(data),foo) returns not nil") } if deck.Put(len(data), "foo") != nil { return fmt.Sprintf("Put(len(data),foo) returns not nil") } if deck.String() != "Deque"+fmt.Sprintf("%v", data) { return fmt.Sprintf("String() returns \"%v\" instead of \"%v\"", deck.String(), "Deque"+fmt.Sprintf("%v", data)) } return "" }
// Parses the relevant configuration files and sets // the config variables accordingly. func ReadConfig() { conf := map[string]map[string]string{"": map[string]string{}} var tftp_mappings deque.Deque // [general]/pxelinux-cfg-hook is deprecated and only supported for // backwards compatibility. It will be converted to patterns later. // That's why this is a local variable and not a global one. pxeLinuxCfgHookPath := "/usr/lib/go-susi/generate_pxelinux_cfg" for _, configfile := range []string{ClientConfigPath, ServerConfigPath} { if configfile == "" { continue } file, err := os.Open(configfile) if err != nil { if os.IsNotExist(err) { /* File does not exist is not an error that needs to be reported */ } else { util.Log(0, "ERROR! ReadConfig: %v", err) } continue } defer file.Close() input := bufio.NewReader(file) current_section := "" for { var line string line, err = input.ReadString('\n') if err != nil { break } if comment := strings.Index(line, "#"); comment >= 0 { line = line[0:comment] } line = strings.TrimSpace(line) if len(line) > 2 && line[0] == '[' && line[len(line)-1] == ']' { current_section = line if _, ok := conf[current_section]; !ok { conf[current_section] = map[string]string{} } } i := strings.Index(line, "=") if i >= 0 { key := strings.TrimSpace(line[0:i]) value := strings.TrimSpace(line[i+1:]) if key != "" { if current_section == "[tftp]" && key[0] == '/' && len(key) >= 2 { tftp_mappings.Push(key[1:]) tftp_mappings.Push(value) } else { conf[current_section][key] = value } } } } if err != io.EOF { util.Log(0, "ERROR! ReadConfig: %v", err) // Do not return. Try working with whatever we got out of the file. } } for sectionname, section := range conf { if sectkey, ok := section["key"]; ok { ModuleKeys = append(ModuleKeys, sectkey) ModuleKey[sectionname] = sectkey } } TLSRequired = len(ModuleKey) == 0 if general, ok := conf["[general]"]; ok { if logfile, ok := general["log-file"]; ok { LogFilePath = logfile } if failogdir, ok := general["fai-log-dir"]; ok { FAILogPath = failogdir } if kernel_list_hook, ok := general["kernel-list-hook"]; ok { KernelListHookPath = kernel_list_hook } if package_list_hook, ok := general["package-list-hook"]; ok { PackageListHookPath = package_list_hook } if user_msg_hook, ok := general["user-msg-hook"]; ok { UserMessageHookPath = user_msg_hook } if pxelinux_cfg_hook, ok := general["pxelinux-cfg-hook"]; ok { pxeLinuxCfgHookPath = pxelinux_cfg_hook } if new_config_hook, ok := general["new-config-hook"]; ok { NewConfigHookPath = new_config_hook } if trigger_action_hook, ok := general["trigger-action-hook"]; ok { TriggerActionHookPath = trigger_action_hook } if registered_hook, ok := general["registered-hook"]; ok { RegisteredHookPath = registered_hook } if activated_hook, ok := general["activated-hook"]; ok { ActivatedHookPath = activated_hook } if detect_hardware_hook, ok := general["detect-hardware-hook"]; ok { DetectHardwareHookPath = detect_hardware_hook } if fai_progress, ok := general["fai-progress-hook"]; ok { FAIProgressHookPath = fai_progress } if fai_savelog, ok := general["fai-savelog-hook"]; ok { FAISavelogHookPath = fai_savelog } } if server, ok := conf["[server]"]; ok { if dnslookup, ok := server["dns-lookup"]; ok { dnslookup = strings.TrimSpace(dnslookup) if dnslookup != "false" && dnslookup != "true" { util.Log(0, "ERROR! ReadConfig: [server]/dns-lookup must be \"true\" or \"false\", not \"%v\"", dnslookup) } DNSLookup = (dnslookup == "true") } if port, ok := server["port"]; ok { port = strings.TrimSpace(port) i := strings.Index(ServerSourceAddress, ":") ServerSourceAddress = ServerSourceAddress[:i+1] + port i = strings.Index(ServerListenAddress, ":") ServerListenAddress = ServerListenAddress[:i+1] + port } if ip, ok := server["ip"]; ok { PreferredServer = ip } if uri, ok := server["ldap-uri"]; ok { LDAPURI = uri } if base, ok := server["ldap-base"]; ok { LDAPBase = base } if newsysbase, ok := server["new-systems-base"]; ok { IncomingOU = newsysbase } if IncomingOU[len(IncomingOU)-1] == ',' { IncomingOU += LDAPBase } if admin, ok := server["ldap-admin-dn"]; ok { LDAPAdmin = admin } if pw, ok := server["ldap-admin-password"]; ok { err := ioutil.WriteFile(LDAPAdminPasswordFile, []byte(pw), 0600) if err != nil { util.Log(0, "ERROR! Could not write admin password to file: %v", err) } } if user, ok := server["ldap-user-dn"]; ok { LDAPUser = user } if pw, ok := server["ldap-user-password"]; ok { err := ioutil.WriteFile(LDAPUserPasswordFile, []byte(pw), 0600) if err != nil { util.Log(0, "ERROR! Could not write user password to file: %v", err) } } } if client, ok := conf["[client]"]; ok { if port, ok := client["port"]; ok { ClientPorts = strings.Fields(strings.Replace(port, ",", " ", -1)) } } if faimon, ok := conf["[faimon]"]; ok { if port, ok := faimon["port"]; ok { FAIMonPort = port } } if tftp, ok := conf["[tftp]"]; ok { if port, ok := tftp["port"]; ok { TFTPPort = port } } if tlsconf, ok := conf["[tls]"]; ok { if cacert, ok := tlsconf["ca-certificate"]; ok { CACertPath = []string{cacert} } if cert, ok := tlsconf["certificate"]; ok { CertPath = cert } if certkey, ok := tlsconf["keyfile"]; ok { CertKeyPath = certkey } } // Backwards compatibility: Convert [general]/pxelinux-cfg-hook to patterns // as described in manual. if pxeLinuxCfgHookPath != "" { tftp_mappings.Insert("|" + pxeLinuxCfgHookPath) tftp_mappings.Insert("^pxelinux.cfg/01-(?P<macaddress>[0-9a-f]{2}(-[0-9a-f]{2}){5})$") tftp_mappings.Insert("") tftp_mappings.Insert("/^pxelinux.cfg/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$") } for !tftp_mappings.IsEmpty() { file := tftp_mappings.Pop().(string) pattern := tftp_mappings.Pop().(string) if pattern[0] != '^' { pattern = "^" + regexp.QuoteMeta(pattern) + "$" file = strings.Replace(file, "$", "$$", -1) } re, err := regexp.Compile(pattern) if err != nil { util.Log(0, "ERROR! ReadConfig: In section [tftp]: Error compiling regex \"%v\": %v", pattern, err) } else { TFTPRegexes = append(TFTPRegexes, re) TFTPReplies = append(TFTPReplies, file) } } // The [ServerPackages] section must be evaluated AFTER the [server] // section, because the manual says that [ServerPackages]/dns-lookup takes // precedence over [server]/dns-lookup. if serverpackages, ok := conf["[ServerPackages]"]; ok { if addresses, ok := serverpackages["address"]; ok && addresses != "" { PeerServers = append(PeerServers, strings.Fields(strings.Replace(addresses, ",", " ", -1))...) } if dnslookup, ok := serverpackages["dns-lookup"]; ok { dnslookup = strings.TrimSpace(dnslookup) if dnslookup != "false" && dnslookup != "true" { util.Log(0, "ERROR! ReadConfig: [ServerPackages]/dns-lookup must be \"true\" or \"false\", not \"%v\"", dnslookup) } DNSLookup = (dnslookup == "true") } if lookupdomains, ok := serverpackages["domains"]; ok { for _, dom := range strings.Fields(strings.Replace(lookupdomains, ",", " ", -1)) { if dom[0] != '.' { dom = "." + dom } LookupDomains = append(LookupDomains, dom) } } } if LDAPAdmin == "" { RunServer = false } ClientPorts = append(ClientPorts, ServerListenAddress[strings.Index(ServerListenAddress, ":")+1:]) if PreferredServer != "" && strings.Index(PreferredServer, ":") < 0 { PreferredServer += ServerListenAddress[strings.Index(ServerListenAddress, ":"):] } serversInConfigFile := make([]string, len(PeerServers)) copy(serversInConfigFile, PeerServers) if PreferredServer != "" { serversInConfigFile = append(serversInConfigFile, PreferredServer) } for _, srv := range serversInConfigFile { prefhost, _, err := net.SplitHostPort(srv) if err == nil { prefip := net.ParseIP(prefhost) if prefip != nil { ServerIPsFromConfigFile = append(ServerIPsFromConfigFile, prefip) } else { ServerNamesFromConfigFile = append(ServerNamesFromConfigFile, prefhost) } } } file, err := os.Open(ServersOUConfigPath) if err != nil { if os.IsNotExist(err) { /* File does not exist is not an error that needs to be reported */ } else { util.Log(0, "ERROR! ReadConfig: %v", err) } } else { defer file.Close() input := bufio.NewReader(file) for { var line string line, err = input.ReadString('\n') if err != nil { break } line = strings.TrimSpace(line) if line != "" { LDAPServerOUs = append(LDAPServerOUs, line) } } } }